Looking Back At SmashingConf SF 2022

Last month, we hosted our first offline + online conference in San Francisco. It was also our first in-person conference since 2019, and we were extremely excited — and of course, a little apprehensive — to get back to in-person conferences again. In this article, we would like to share our perspective as organizers and take a look at our upcoming events.

Why We Were So Excited

Over the last few years, we got a lot better at postponing conferences, and we were wondering if we were still good at actually organizing them. Some things definitely felt a bit rusty, but lots of things were back to normal pretty quickly. I think every speaker started with a heartfelt, “I am so happy to be back on an actual stage looking you in the eye,” before diving into their actual talk. Our attendees helped massively by providing proof of vaccination before or during check-in, and the atmosphere was very friendly and festive overall.

June 20 & 21, 2022 was the date of our return to hosting in-person events, and it was a hit!

We love bringing people together. And yes, online events are amazing and offer plenty of opportunities for connection. But seeing old friends and new—and being able to give some people a long-overdue hug—was something we all missed very much.

And because Smashing is an all-remote team, we had not seen each other for 2.5 years ‐ since our New York event back in October 2019. And yes, all of us have aged a bit (with less or greyer hairs and more wrinkles and bags under our eyes), but the amount of energy we get from these events is just amazing. We saw many people making new friends, reconnect with old friends, get inspired, eat, drink and mingle — which is just incredible.

The Program of The Conference

Our program consisted of two days of single-track talks, ‘sandwiched’ by two days of immersive workshops. The speakers and workshops provided a strong mix of design and front-end topics. At Smashing, we strongly believe in conferences with a wide range of topics (as you can learn something from every talk), and hence don’t do conferences focused on a single thing (we do that in our community Meets events). Topics ranged from CSS, Design Systems, and UX Writing to learning how to talk again. And of course, there were surprises such as Addy Osmani (as our mystery speaker) — speaking about life lessons rather than web performance this time.

The mystery speaker for #SmashingConf SF is… @addyosmani!

First time I’ve seen a talk of his live!

His talk on life lessons is PERFECT timing for me as I make sense of reinventing how I self-actualize and my priorities turning 30 during the pandemic! 🙌🏾 pic.twitter.com/OltgthvG17

— Kevin Lozandier @ #SmashingConf (@KevinLozandier) June 22, 2022

Day 1

Speaker Name Talk Title
Brad Frost Creating Themeable Design Systems
Kate Kalcevich Scaling Up Accessibility
Robin Marx Married to HTTP/3
Shubhie Panicker De-Mystifying Leadership
Miriam Suzanne Styling the Intrinsic Web (with Container Queries, Layers, and Scope)
Elliot Jay Stocks Typography for the People

Day 2

Speaker Name Talk Title
Addy Osmanix Life Lessons by our Mystery Speaker
Harry Roberts Get Your Head Straight
Vitaly Friedman Designing for Complex UIs
Sophie Tahran Designing with Words
Dan Rubin We Don’t Talk Anymore
Jhey Tompkins Take Your Skills to the Moon with Creative Coding

Besides the program throughout the days, we had some great evening events, starting with the Jam sessions — which were a mix of short talks and mingling — and a legendary Smashing party where we brushed up on our gaming skills (and late 20th-century hits) and of course the dancing to Tobi’s fantastic DJ skills. Early risers were invited to participate in a 5K Golden Gate Bridge run each conference morning, too.

Of course all sessions were recorded, and the videos of the conference will be released in a few weeks, so please stay tuned! 💌

The Venue

This year we returned to the fabulous Fort Mason and really made use of the space. The main conference was held at the historic Cowell Theater. We were lucky to have fantastic weather, and this iconic location ‐ with its scenic views of San Francisco Bay and the Golden Gate Bridge ‐ was gorgeous as ever. The workshops were hosted in Fort Mason’s light - filled meeting rooms, giving attendees the chance to deep-dive into design and development topics in a smaller, classroom-style setting.

Our second location was virtual; this time, we also hosted an online version of the event via our online Vi.to hub. With the ability to follow the high-quality conference live stream from home (or office), ask questions in the chat, and see some light-hearted backstage interviews, this online experience was a great option that we will continue to offer in the future.

Ted Boyer, a Seattle-based designer and front-end developer, has been following the stream remotely and has written about his experience watching SmashingConf SF 2022 online.

A Smashing Conference is always designed to be unique in some ways. So of course, on stage, we also have our dear friend Tobi Baldower DJing between the talks, and doing sketch notes in music live. We can’t even imagine a Smashing Conference without Tobi, and he has plenty of fans around the world these days! The energy Tobi has is absolutely incredible, and it always contributes to the atmosphere of the event. You can support DJ Tobi by purchasing his music on Bandcamp (and please do so if you can!).

What’s Next?

We did some sleeping first, interspersed by some light post-conference admin to wrap things up. And now we are putting the finishing touches on our upcoming offline + online conferences in:

It is really cool to see our team so incredibly inspired to get back to organizing more and even better “hybrid” experiences in the future.

Great conference to remind, connect and find your passion. Until next time #smashingconf pic.twitter.com/w4vrajlvwH

— Rosa Arcadeia Buendia (@lapilitorres) June 23, 2022

Said it once, but have to say it again: the energy of bringing people together is just fantastic, and working on these events with a great team of amazing participants is something we hope we can do for a looooong time to come. Every SmashingConf has a unique lineup of speakers and workshops, and we do our best to make every talk as valuable as possible.

It goes without saying that we’d be absolutely delighted and honored to meet you there — in Freiburg and/or in New York.

Collective #709





HyperUI

Free Tailwind CSS components that can be used in your next project. Perfect for Laravel, Rails, React, Vue and more.

Check it out












FortuneSheet

A drop-in JavaScript spreadsheet library that provides rich features like Excel and Google Sheets.

Check it out




Fleet (beta)

Fleet is the blazing fast build tool for Rust. Compiling with Fleet is up-to 5x faster than with cargo.

Check it out



The post Collective #709 appeared first on Codrops.

Smashing Podcast Episode 36 With Miriam Suzanne: What Is The Future Of CSS?

In this episode, we’re starting our new season of the Smashing Podcast with a look at the future of CSS. What new specs will be landing in browsers soon? Drew McLellan talks to expert Miriam Suzanne to find out.

Show Notes

Weekly Update

Transcript

Drew McLellan: She’s an artist, activist, teacher and web developer. She’s a co-founder of OddBird, a provider of custom web applications, developer tools, and training. She’s also an invited expert to the CSS Working Group and a regular public speaker and author sharing her expertise with audiences around the world. We know she knows CSS both backwards and forwards, but did you know she once won an egg and spoon race by taking advantage of a loophole involving macaroni? My smashing friends, please welcome Miriam Suzanne. Hi, Miriam. How are you?

Miriam Suzanne: I’m smashing, thank you.

Drew: That’s good to hear. I wanted to talk to you today about some of the exciting new stuff that’s coming our way in CSS. It feels like there’s been a bit of an acceleration over the last five years of new features making their way into CSS and a much more open and collaborative approach from the W3C with some real independent specialists like yourself, Rachel Andrew, Lea Verou and others contributing to the working group as invited experts. Does it feel like CSS is moving forward rapidly or does it still feel horribly slow from the inside?

Miriam: Oh, it’s both, I think. It is moving quite fast and quite fast is still sometimes very slow because there’s just so many considerations. It’s hard to really land something everywhere very quickly.

Drew: It must feel like there’s an awful lot of work happening on all sorts of different things and each of them edging forward very, very slowly, but when you look at the cumulative effect, there’s quite a lot going on.

Miriam: Yeah, exactly, and I feel like I don’t know what kicked off that change several years ago, whether it was grid and flexbox really kicked up interest in what CSS could be, I think, and there’s just been so much happening. But it’s interesting watching all the discussions and watching the specs. They all refer to each other. CSS is very tied together. You can’t add one feature without impacting every other feature and so all of these conversations have to keep in mind all of the other conversations that are happening. It’s really a web to try to understand how everything impacts everything else.

Drew: It feels like the working group very much always looking at what current practice is and seeing what holes people are trying to patch, what problems they’re trying to fix, often with JavaScript, and making a big messy ball of JavaScript. Is that something that’s a conscious effort or does it just naturally occur?

Miriam: I would say it’s very conscious. There’s also a conscious attempt to then step back from the ideas and say, "Okay, this is how we’ve solved them in JavaScript or using hacks, workarounds, whatever." We could just pave that cow path, but maybe there’s a better way to solve it once it’s native to CSS and so you see changes to things like variables. When they move from preprocessors like Sass and Less to CSS, they become something new. And that’s not always the case, sometimes the transition is pretty seamless, it’s more just take what’s already been designed and make it native. But there’s a conscious effort to think through that and consider the implications.

Drew: Yeah, sometimes a small workaround is hiding quite a big idea that could be more useful in itself.

Miriam: And often, hiding overlapped ideas. I was just reading through a lot of the issues around grid today because I’ve been working on responsive components, things like that, and I was like, "Okay, what’s happening in the grid space with this?" And there’s so many proposals that mix and overlap in really interesting ways. It can be hard to separate them out and say, "Okay, should we solve these problems individually or do we solve them as grouped use cases? How exactly should that be approached?"

Drew: I guess that can be, from the outside, that might seem like a frustrating lack of progress when you say, "Why can’t this feature be implemented?" It’s because when you look at that feature, it explodes into something much bigger that’s much harder to solve.

Miriam: Exactly.

Drew: Hopefully, solving the bigger problem makes all sorts of other things possible. I spent a lot of my career in a position where we were just sort of clamoring for something, anything, new to be added to CSS. I’m sure that’s familiar to you as well. It now seems like it’s almost hard to keep track of everything that’s new because there’s new things coming out all the time. Do you have any advice for working front-enders of how they can keep track of all the new arrivals in CSS? Are there good resources or things they should be paying attention to?

Miriam: Yeah, there are great resources if you really want a curated, a sense of what you should be watching. But that’s Smashing Magazine, CSS-Tricks, all of the common blogs and then various people on Twitter. Browser implementers as well as people on the working group as well as people that write articles. Stephanie Eckles comes to mind, ModernCSS. There’s a lot of resources like that. I would also say, if you keep an eye on the release notes from different browsers, they don’t come out that often, it’s not going to spam your inbox every day. You’ll often see a section in the release notes on what have they released related to CSS. And usually in terms of features, it’s just one or two things. You’re not going to become totally overwhelmed by all of the new things landing. They’ll come out six weeks to a couple of months and you can just keep an eye on what’s landing in the browsers.

Drew: Interesting point. I hadn’t thought of looking at browser release notes to find this stuff. Personally, I make efforts to follow people on Twitter who I know would share things, but I find I just miss things on Twitter all the time. There’s lots of cool stuff that I never get to see.

Drew: In that spirit, before we look too far into the future into what’s under development at the moment, there are quite a few bits of CSS that have already landed in browsers that might be new to people and they might be pretty usable under a lot of circumstances. There are certainly things that I’ve been unaware of.

Drew: One area that comes to mind is selectors. There’s this "is" pseudo-class function, for example. Is that like a jQuery "is" selector, if you remember those? I can barely remember those.

Miriam: I didn’t use jQuery enough to say.

Drew: No. Now even saying that, it’s so dusty in my mind, I’m not even sure that was a thing.

Miriam: Yeah, "is" and "where", it’s useful to think of them together, both of those selectors. "Is" sort of landed in most browsers a little bit before "where", but at this point I think both are pretty well-supported in modern browsers. They let you list a number of selectors inside of a single pseudo-class selector. So you say, ":is" or ":where" and then in parentheses, you can put any selectors you want and it matches an element that also matches the selectors inside. One example is, you can say, "I want to style all the links inside of any heading." So you can say "is", H1, H2, H3, H4, H5, H6, put a list inside of "is", and then, after that list say "A" once. And you don’t have to repeat every combination that you’re generating there. It’s sort of a shorthand for bringing nesting into CSS. You can create these nested "like" selectors. But they also do some interesting things around specificity... Sorry, what were you going to say?

Drew: I guess it’s just useful in making your style sheet more readable and easy to maintain if you’re not having to longhand write out every single combination of things.

Miriam: Right. The other interesting thing you can do with it is you can start to combine selectors. So you can say, "I’m only targeting something that matches both the selectors outside of "is" and the selectors inside of "is"". It has to match all of these things." So you can match several selectors at once, which is interesting.

Drew: Where does "where" come into it if that’s what "is" does?

Miriam: Right. "Where" comes into it because of the way that they handle specificity. "Is" handles specificity by giving you the entire selector gets the specificity of whatever is highest specificity inside of "is." "Is" can only have one specificity and it’s going to be the highest of any selector inside. If you put an "id" inside it, it’s going to have the specificity of an "id." Even if you have an "id" and a class, two selectors, inside "is", It’s going to have the specificity of the "id."

Miriam: That defaults to a higher specificity. "Where" defaults to a zero specificity, which I think is really interesting, especially for defaults. I want to style an audio element where it has controls, but I don’t want to add specificity there, I just want to say where it’s called for controls, where it has the controls attribute, add this styling to audio. So a zero-specificity option. Otherwise, they work the same way.

Drew: Okay. So that means with a zero specificity, it means that, then, assuming that somebody tries to style those controls in the example, they’re not having to battle against the styles that have already been set.

Miriam: That’s right, yeah. There’s another interesting thing inside of both of those where they’re supposed to be resilient. Right now, if you write a selector list and a browser doesn’t understand something in that selector list, it’s going to ignore all of the selectors in the list. But if you do that inside of "is" or "where", if an unknown selector is used in a list inside of "is" or "where", it should be resilient and the other selectors should still be able to match.

Drew: Okay, so this is that great property of CSS, that if it doesn’t understand something, it just skips over it.

Miriam: Right.

Drew: And so, you’re saying that if there’s something that it doesn’t understand in the list, skip over the thing it doesn’t understand, but don’t throw the baby out with the bathwater, keep all the others and apply them.

Miriam: Exactly.

Drew: That’s fascinating. And the fact that we have "is" and "where" strikes me as one of those examples of something that sounds like an easy problem. "Oh, let’s have an "is" selector." And then somebody says, "But what about specificity?"

Miriam: Right, exactly.

Drew: How are we going to work that out?

Miriam: Yeah. The other interesting thing is that it comes out of requests for nesting. People wanted nested selectors similar to what Sass has and "is" and "where" are, in some ways, a half step towards that. They will make the nested selectors easier to implement since we already have a way to, what they call "de-sugar" them. We can de-sugar them to this basic selector.

Drew: What seems to me like the dustiest corners of HTML and CSS are list items and the markers that they have, the blitz or what have you. I can remember, probably back in Frontpage in the late ’90s, trying to style, usually with proprietary Microsoft properties, for Internet Explorer back in the day. But there’s some good news on the horizon for lovers of markers, isn’t there?

Miriam: Yeah, there’s a marker selector that’s really great. We no longer have to remove the markers by saying... How did we remove markers? I don’t even remember. Changing the list style to none.

Drew: List style, none. Yup.

Miriam: And then people would re-add the markers using "before" pseudo-element. And we don’t have to do that anymore. With the marker pseudo-element, we can style it directly. That styling is a little bit limited, particularly right now, it’s going to be expanding out some, but yeah, it’s a really nice feature. You can very quickly change the size, the font, the colors, things like that.

Drew: Can you use generated content in there as well?

Miriam: Yes. I don’t remember how broad support is for the generated content, but you should be able to.

Drew: That’s good news for fans of lists, I guess. There’s some new selectors. This is something that I came across recently in a real-world project and I started using one of these before I realized actually it wasn’t as well supported as I thought, because it’s that new. And that’s selectors to help when "focus" is applied to elements. I think I was using "focus within" and there’s another one, isn’t there? There’s-

Miriam: "Focus visible."

Drew: What do they do?

Miriam: Browsers, when they’re handling "focus", they make some decisions for you based on whether you’re clicking with a mouse or whether you’re using a keyboard to navigate. Sometimes they show "focus" and sometimes they don’t, by default. "Focus visible" is a way for us to tie into that logic and say, "When the browser thinks focus should be visible, not just when an item has focus, but when an item has focus and the browser thinks focus needs to be visible, then apply these styles." That’s useful for having outline rings on focus, but not having them appear when they’re not needed, when you’re using a mouse and you don’t really need to know. You’ve clicked on something, you know that you’ve focused it, you don’t need the styling there. "Focus visible" is really useful for that. "Focus within" allows you to say, "Style the entire form when one of its elements has focus," which is very cool and very powerful.

Drew: I think I was using it on a dropdown menu navigation which is-

Miriam: Oh, sure.

Drew: ... a focus minefield, isn’t it?

Miriam: Mm-hmm (affirmative).

Drew: And "focus within" was proven very useful there until I didn’t have it and ended up writing a whole load of JavaScript to recreate what I’d achieved very simply with CSS before it.

Miriam: Yeah, the danger always with new selectors is how to handle the fallback.

Drew: One thing I’m really excited about is this new concept in CSS of aspect ratio. Are we going to be able to say goodbye to the 56% top padding hack?

Miriam: Oh, absolutely. I’m so excited to never use that hack again. I think that’s landing in browsers. I think it’s already available in some and should be coming to others soon. There seems to be a lot of excitement around that.

Drew: Definitely, it’s the classic problem, isn’t it, of having a video or something like that. You want to show it in like a 16 by 9 ratio, but you want to set the dimensions on it. But maybe it’s a 4 by 3 video and you have to figure out how to do it and get it to scale with the right-

Miriam: Right, and you want it to be responsive, you want it to fill a whole width, but then maintain its ratio. Yeah, the hacks for that aren’t great. I use one often that’s create a grid, position generated content with a padding top hack, and then absolute position the video itself. It’s just a lot to get it to work the way you want.

Drew: And presumably, that’s going to be much more performance for the layout engines to be able to deal with and-

Miriam: Right. And right away, it’s actually a reason to put width and height values back on to replaced elements like images, in particular, so that even before CSS loads, the browser can figure out what is the right ratio, the intrinsic ratio, even before the image loads and use that in the CSS. We used to strip all that out because we wanted percentages instead and now it’s good to put it back in.

Drew: Yes, I was going to say that when responsive web design came along, we stripped all those out. But I think we lost something in the process, didn’t we, of giving the browser that important bit of information about how much space to reserve?

Miriam: Yeah, and it ties in to what Jen Simmons has been talking about lately with intrinsic web design. The idea with responsive design was basically that we strip out any intrinsic sizing and we replace it with percentages. And now the tools that we have, flex and grid, are actually built to work with intrinsic sizes and it’s useful to put those all back in and we can override them still if we need to. But having those intrinsic sizes is useful and we want them.

Drew: Grid, you mentioned, I think sort of revolutionized the way we think about layout on the web. But it was always sort of tempered a little bit by the fact that we didn’t get subgrid at the same time. Remind us, if you will, what subgrid is all about and where are we now with support?

Miriam: Yeah. Grid establishes a grid parent and then all of its children layout on that grid. And subgrid allows you to nest those and say, "Okay, I want grandchildren to be part of the grandparent grid." Even if I have a DOM tree that’s quite a bit nested, I can bubble up elements into the parent grid, which is useful. But it’s particularly useful when you think about the fact that CSS in general and CSS Grid in particular does this back and forth of some parts of the layout are determined based on the available width of the container. They’re contextual, they’re outside-in. But then also, some parts of it are determined by the sizes of the children, the sizes of the contents, so we have this constant back and forth in CSS between whether the context is in control or whether the contents are in control of the layout. And often, they’re intertwined in very complex ways. What’s most interesting about subgrid is it would allow the contents of grid items to contribute back their sizing to the grandparent grid and it makes that back and forth between contents and context even more explicit.

Drew: Is that the similar problem that has been faced by container queries? Because you can’t really talk about the future of CSS and ask designers and developers what they want in CSS without two minutes in somebody saying, "Ah, container queries, that’s what we want." Is that a similar issue of this pushing and pulling of the two different context to figure out how much space there is?

Miriam: Yeah, they both are related to that context-content question. Subgrid doesn’t have to deal with quite the same problems. Subgrid actually works. It is actually able to pass those values both directions because you can’t change the contents based on the context. We sort of cut off that loop. And the problem with container queries has always been that there’s a potential infinite loop where if we allow the content to be styled based on its context explicitly, and you could say, "When I have less than 500 pixels available, make it 600 pixels wide." You could create this loop where then that size changes the size of the parent, that changes whether the container query applies and on and on forever. And if you’re in the Star Trek universe, the robot explodes. You get that infinite loop. The problem with container queries that we’ve had to solve is how do we cut off that loop.

Drew: Container queries is one of the CSS features that you’re one of the editors for, is that right?

Miriam: Yeah.

Drew: So the general concept is like a media query, where we’re looking at the size of a viewport, I guess, and changing CSS based on it. Container queries are to do that, but looking at the size of a containing element. So I’m a hero image on a page, how much space have I got?

Miriam: Right. Or I’m a grid item in a track. How much space do I have in this track? Yeah.

Drew: It sounds very difficult to solve. Are we anywhere near a solution for container queries now?

Miriam: We are very near a solution now.

Drew: Hooray!

Miriam: There’s still edge cases that we haven’t resolved, but at this point, we’re prototyping to find those edge cases and see if we can solve all of them. But the prototypes we’ve played with so far surprisingly just work in the majority of cases, which has been so fun to see. But it’s a long history. It’s sort of that thing with... Like we get "is" because it’s halfway to nesting. And there’s been so much work over the last 10 years. What looks like the CSS Working Group not getting anywhere on container queries has actually been implementing all of the half steps we would need in order to get here. I came on board to help with this final push, but there’s been so much work establishing containment and all these other concepts that we’re now relying on to make container queries possible.

Drew: It’s really exciting. Is there any sort of timeline now that we might expect them to get into browsers?

Miriam: It’s hard to say exactly. Not all browsers announce their plans. Some more than others. It’s hard to say, but all of the browsers seem excited about the idea. There’s a working prototype in Chrome Canary right now that people can play with and we’re getting feedback through that to make changes. I’m working on the spec. I imagine dealing with some of the complexity in the edge cases. It will take some time for the spec to really solidify, but I think we have a fairly solid proposal overall and I hope that other browsers are going to start picking up on that soon. I know containment, as a half step, is already not implemented everywhere, but I know Igalia is working to help make sure that there’s cross-browser support of containment and that should make it easier for every browser to step up and do the container queries.

Drew: Igalia are an interesting case, aren’t they? They were involved in a lot of the implementation on Grid initially, is that right?

Miriam: Yes. I understand they were hired by Bloomberg or somebody that really wanted grids. Igalia is really interesting. They’re a company that contributes to all of the browsers.

Drew: They’re sort of an outlier, it seems. All the different parties that work on CSS, is mostly, as you’d expect, mostly browser vendors. But yes, they’re there as a sort of more independent developer, which is very interesting.

Miriam: A browser vendor vendor.

Drew: Yes. Definitely. Another thing I wanted to talk to you about is this concept that completely twisted my mind a little bit while I started to think about it. It’s this concept of cascade layers. I think a lot of developers might be familiar with the different aspects of the CSS cascade thing, specificity, source order, importance, origin. Are those the main ones? What are cascade layers? Is this another element of the cascade?

Miriam: Yeah. It is another element very much like those. I think often when we talk about the cascade, a lot of people mainly think of it as specificity. And other things get tied into that. People think of importance as a higher specificity, people think of source order as a lower specificity. That makes sense because, as authors, we spend most of our time in specificity.

Miriam: But these are separate things and importance is more directly tied to origins. This idea of where do styles come from. Do they come from authors like us or browsers, the default styles, or do they come from users? So three basic origins and those layer in different ways. And then importance is there to flip the order so that there’s some balance of control. We get to override everybody by default, but users and browsers can say, "No, this is important. I want control back." And they win.

Miriam: For us, importance acts sort of like a specificity layer because normal author styles and important author styles are right next to each other so it makes sense that we think of them that way. But I was looking at that and I was thinking specificity is this attempt to say... It’s a heuristic. That means it’s a smart guess. And the guess is based on we think the more narrowly targeted something is, probably the more you care about it. Probably. It’s a guess, it’s not going to be perfect, but it gets us partway. And that is somewhat true. The more narrowly we target something, probably the more we care about it so more targeted styles override less targeted styles.

Miriam: But it’s not always true. Sometimes that falls apart. And what happens is, there’s three layers of specificity. There’s id’s, there’s classes and attributes, and there there’s elements themselves. Of those three layers, we control one of them completely. Classes and attributes, we can do anything we want with them. They’re reusable, they’re customizable. That’s not true of either of the other two layers. Once things get complex, we often end up trying to do all of our cascade management in that single layer and then getting angry, throwing up our hands, and adding importance. That’s not ideal.

Miriam: And I was looking at origins because I was going to do some videos teaching the cascade in full, and I thought that’s actually pretty clever. We, as authors, often have styles that come from different places and represent different interests. And what if we could layer them in that same way that we can layer author styles, user styles, and browser styles. But instead, what if they’re... Here’s the design system, here’s the styles from components themselves, here’s the broad abstractions. And sometimes we have broad abstractions that are narrowly targeted and sometimes we have highly repeatable component utilities or something that need to have a lot of weight. What if we could explicitly put those into named layers?

Miriam: Jen Simmons encouraged me to submit that to the working group and they were excited about it and the spec has been moving very quickly. At first, we were all worried that we would end up in a z-index situation. Layer 999,000 something. And as soon as we started putting together the syntax, we found that that wasn’t hard to avoid. I’ve been really excited to see that coming together. I think it’s a great syntax that we have.

Drew: What form does the syntax take on, roughly? I know it’s difficult to mouth code, isn’t it?

Miriam: It’s an "@" rule called "@layer." There’s actually two approaches. You can also use, we’re adding a function to the "@import" syntax so you could import a style sheet into a layer, say, import Bootstrap into my framework layer. But you can also create or add to layers using the "@layer" rule. And it’s just "@layer" and then the name of the layer. And layers get stacked in the order they’re first introduced, which means that even if you’re bringing in style sheets from all over and you don’t know what order they’re going to load, you can, at the top of your document, say, "Here are the layers that I’m planning to load, and here’s the order that I want them in." And then, later, when you’re actually adding styles into those layers, they get moved into the original order. It’s also a way of saying, "Ignore the source order here. I want to be able to load my styles in any order and still control how they should override each other."

Drew: And in its own way, having a list, at the top, of all these different layers is self-documenting as well, because anybody who comes to that style sheet can see the order of all the layers.

Miriam: And it also means that, say, Bootstrap could go off and use a lot of internal layers and you could pull those layers in from Bootstrap. They control how their own layers relate to each other, but you could control how those different layers from Bootstrap relate to your document. So when should Bootstrap win over your layers and when should your layers win over Bootstrap? And you can start to get very explicit about those things without ever throwing the "important" flag.

Drew: Would those layers from an imported style sheet, if that had its own layers, would they all just mix in at the point that the style sheet was added?

Miriam: By default, unless you’ve defined somewhere else previously how to order those layers. So still, your initial layer ordering would take priority.

Drew: If Bootstrap, for example, had documented their layers, would you be able to target a particular one and put that into your layer stack to change it?

Miriam: Yes.

Drew: So it’s not an encapsulated thing that all moves in one go. You can actually pull it apart and...

Miriam: It would depend... We’ve got several ideas here. We’ve built in the ability to nest layers that seemed important if you were going to be able to import into a layer. You would have to then say, "Okay, I’ve imported all of Bootstrap into a layer called frameworks," but they already had a layer called defaults and a layer called widgets or whatever. So then I want a way to target that sublayer. I want to be able to say "frameworks widgets" or "frameworks defaults" and have that be a layer. So we have a syntax for that. We think that all of those would have to be grouped together. You couldn’t pull them apart if they’re sublayered. But if Bootstrap was giving you all those as top level layers, you could pull them in at the top level, not group them. So we have ways of doing both grouping or splitting apart.

Drew: And the fact that you can specify a layer that something is imported into that doesn’t require any third-party script to know about layers or have implemented it, presumably, it just pulls that in at the layer you specify.

Miriam: Right.

Drew: That would help with things pretty much like Bootstrap and that sort of thing, but also just with the third party widgets you’re then trying to fight with specificity to be able to re-style them and they’re using id’s to style things and you want to change the theme color or something and you having to write these very specific... You can just change the layer order to make sure that your layers would win in the cascade.

Miriam: Yup. That’s exactly right. The big danger here is backwards compatibility. It’s going to be a rough transition in some sense. I can’t imagine any way of updating the cascade or adding the sort of explicit rules to the cascade without some backwards compatibility issues. But older browsers are going to ignore anything inside a layer rule. So that’s dangerous. This is going to take some time. I think we’ll get it implemented fairly quickly, but then it will still take some time before people are comfortable using it. And there are ways to polyfill it particularly using "is." The "is selector gives us a weird little polyfill that we’ll be able to write. So people will be able to use the syntax and polyfill it, generate backwards-compatible CSS, but there will be some issues there in the transition.

Drew: Presumably. And you’re backwards-compatible to browsers that support "is."

Miriam: That’s right. So it gets us a little farther, but not... It’s not going to get us IE 11.

Drew: No. But then that’s not necessarily a bad thing.

Miriam: Yeah.

Drew: It feels like a scoping mechanism but it’s not a scoping mechanism, is it, layers? It’s different because a scope is a separate thing and is actually a separate CSS feature that there’s a draft in the works for, is that right?

Miriam: Yeah, that’s another one that I’m working on. I would say, as with anything in the cascade, they have sort of an overlap. Layers overlap with specificity and both of them overlap with scope.

Miriam: The idea with scope, what I’ve focused on, is the way that a lot of the JavaScript tools do it right now. They create a scope by generating a unique class name, and then they append that class name to everything they consider within a scope. So if you’re using "view" that’s everything within a view component template or something. So they apply it to every element in the HTML that’s in the scope and then they also apply it to every single one of your selectors. It takes a lot of JavaScript managing and writing these weird strings of unique ids.

Miriam: But we’ve taken the same idea of being able to declare a scope using an "@scope" rule that declares not just the root of the scope, not just this component, but also the lower boundaries of that scope. Nicole Sullivan has called this "donut scope", the idea that some components have other components inside of them and the scope only goes from the outer boundaries to that inner hole and then other things can go in that hole. So we have this "@scope" rule that allows you to declare both a root selector and then say "to" and declare any number of lower boundaries. So in a tab component it might be "scope tabs to tab contents" or something so you’re not styling inside of the content of any one tab. You’re only scoping between the outer box and that inner box that’s going to hold all the contents.

Drew: So it’s like saying, "At this point, stop the inheritance."

Miriam: Not exactly, because it doesn’t actually cut off inheritance. The way I’m proposing it, what it does is it just narrows the range of targeted elements from a selector. So any selector you put inside of the scope rule will only target something that is between the root and the lower boundaries and it’s a targeting issue there. There is one other part of it that we’re still discussing exactly how it should work where, the way I’ve proposed it, if we have two scopes, let’s call them theme scopes. Let’s say we have a light theme and a dark theme and we nest them. Given both of those scopes, both of them have a link style, both of those link styles have the same specificity, they’re both in scopes. We want the closer scope to win in that case. If I’ve got nested light and dark and light and dark, we want the closest ancestor to win. So we do have that concept of proximity of a scope.

Drew: That’s fascinating. So scopes are the scope of the targeting of a selector. Now, I mentioned this idea of inheritance. Is there anything in CSS that might be coming or might exist already that I didn’t know about that will stop inheritance in a nice way without doing a massive reset?

Miriam: Well, really, the way to stop inheritance is with some sort of reset. Layers would actually give you an interesting way to think about that because we have this idea of... There’s already a "revert" rule. We have an "all" property, which sets all properties, every CSS property, and we have a "revert" rule, which reverts to the previous origin. So you can say "all revert" and that would stop inheritance. That would revert all of the properties back to their browser default. So you can do that already.

Miriam: And now we’re adding "revert layer", which would allow you to say, "Okay I’m in the components layer. Revert all of the properties back to the defaults layer." So I don’t want to go the whole way back to the browser defaults, I want to go back to my own defaults. We will be adding something like that in layers that could work that way.

Miriam: But a little bit, in order to stop inheritance, in order to stop things from getting in, I think that belongs more in the realm of shadow DOM encapsulation. That idea of drawing hard boundaries in the DOM itself. I’ve tried to step away from that with my scope proposal. The shadow DOM already is handling that. I wanted to do something more CSS-focused, more... We can have multiple overlapping scopes that target different selectors and they’re not drawn into the DOM as hard lines.

Drew: Leave it to someone else, to shadow DOM. What stage are these drafts at, the cascade layers and scope? How far along the process are they?

Miriam: Cascade layers, there’s a few people who want to reconsider the naming of it, but otherwise, the spec is fairly stable and there’s no other current issues open. Hopefully, that will be moving to candidate recommendation soon. I expect browsers will at least start implementing it later this year. That one is the farthest along because for browsers, it’s very much the easiest to conceptualize and implement, even if it may take some time for authors to make the transition. That one is very far along and coming quickly.

Miriam: Container queries are next in line, I would say. Since we already have a working prototype, that’s going to help a lot. But actually defining all of the spec edge cases... Specs these days are, in large part, "How should this fail?" That’s what we got wrong with CSS 1. We didn’t define the failures and so browsers failed differently and that was unexpected and hard to work with. Specs are a lot about dealing with those failures and container queries are going to have a lot of those edge cases that we have to think through and deal with because we’re trying to solve weird looping problems. It’s hard to say on that one, because we both have a working prototype ahead of any of the others, but also it’s going to be a little harder to spec out. I think there’s a lot of interest, I think people will start implementing soon, but I don’t know exactly how long it’ll take.

Miriam: Scope is the farthest behind of those three. We have a rough proposal, we have a lot of interest in it, but very little agreement on all the details yet. So that one is still very much in flux and we’ll see where it goes.

Drew: I think it’s amazing, the level of thought and work the CSS Working Group are putting into new features and the future of CSS. It’s all very exciting and I’m sure we’re all very grateful for the clever folks like yourself who spend time thinking about it so that we get new tools to use. I’ve been learning all about what’s coming down the pike in CSS, what have you been learning about lately, Miriam?

Miriam: A big part of what I’m learning is how to work on the spec process. It’s really interesting and I mean the working group is very welcoming and a lot of people there have helped me find my feet and learn how to think about these things from a spec perspective. But I have a long ways to go on that and learning exactly how to write the spec language and all of that. That’s a lot in my mind.

Miriam: Meanwhile, I’m still playing with grids and playing with custom properties. And while I learned both of those, I don’t know, five years ago, there’s always something new there to discover and play with, so I feel like I’m never done learning them.

Drew: Yup. I feel very much the same. I feel like I’m always a beginner when it comes to a lot of CSS.

Drew: If you, dear listener, would like to hear more from Miriam, you can find her on Twitter where she’s @TerribleMia, and her personal website is miriamsuzanne.com. Thanks for joining us today, Miriam. Do you have any parting words?

Miriam: Thank you, it’s great chatting with you.

Learning Resources In Challenging Times: Online Workshops, Meetups And Events

Learning Resources In Challenging Times: Online Workshops, Meetups And Events

Learning Resources In Challenging Times: Online Workshops, Meetups And Events

Iris Lješnjanin

In these current strange times of isolation and social distancing (with almost all events and conferences being cancelled), it can be quite difficult to feel connected to family, friends and colleagues. Here at Smashing, we believe that is is now more important than ever to stay in touch and support each other. Behind the scenes, the team is working tirelessly on ways to keep the community connected, and oh boy do we have a lot of things in store for you! You didn’t really think we’d give up that easily, did you?

Your workplace may look a lot like Topple’s, but even if it isn’t, make yourself comfortable! We’ll help you boost your skills online and learn practical, actionable insights from experts in the industry.

We’ve been busy over the last few weeks, and we’re not stopping yet! We have online workshops, SmashingConf Live, Smashing Meets and last but not least, Smashing TV coming right at your fingertips! But first, let’s see what else we’ve been up to…

Look What’s Cookin’!

Exciting times! Click!, our latest Smashing book, is available for pre-order with a friendly discount — you can already start reading the eBook until your printed copy arrives at your doorstep. Written by Paul Boag and beautifully designed by Veerle Pieters, the book is split into 11 chapters: from exploring the psychology of decision making and how to measure conversion to exploring ways of how to encourage users to act without alienating them.

There is no shortage of books on marketing and UX, but when it comes to bridging the gap between the two, many of us struggle to find the right balance. Pre-order today →

Of course, if you’re feeling smashing today, we’d like to invite you join the Smashing family and get the eBook for free (among with many other eBooks and a few fancy cats!).

Learning And Networking, The Smashing Way

Despite the current circumstances, we’re keen to find ways in which we can offer Smashing experiences to anyone interested in learning from experts in our industry — without needing to leave your desk! We’ve been asking what type of resources you’d like to have, and so all of the following online events is what has landed in our Smashing wishing well. Thank you to everyone who has shared their thoughts and feedback — we’ve been all ears!

1. Online Workshops (May–July)

Topple the Cat ready for the new adventureOur friendly online front-end/UX workshops are bound to boost your skills and help you gain practical, actionable insights from experts in the industry — live. There will be plenty of insightful takeaways, exercises, slides, recordings and friendly Q&A time. Of course, we’re happy to provide discounts for large groups and students.

We already have you covered for the next three months — make sure to save your spot as soon as you can:

When? What? Who?
May 7–22 Advanced CSS/Sass Miriam Suzanne
May 12–26 Smart Interface Design Patterns Vitaly Friedman
May 28 – June 12 Web Performance Masterclass Harry Roberts
June 11–12 The CSS Layout Masterclass Rachel Andrew
June 16–30 Front-End Accessibility Masterclass Marcy Sutton
June 18–26 Building Modern HTML Emails Rémi Parmentier
July 2–17 Buy! The eCommerce UX Workshop Vitaly Friedman
July 7–21 Design Systems Brad Frost

Note: If you’re also interested in how you too can run online workshops, listen to Smashing Podcast episode 14 with Rachel Andrew in which she talks about running online workshops and how a traditional event can adapt when participants can’t attend in person.

2. SmashingConf Live (June 9–10)

Topple the Cat sitting on a comfortable couch with a laptop on its lapMeet SmashingConf Live (June 9–10), a truly smashing, friendly online conference on front-end & UX. With interactive live sessions, practical insights, accessible speakers, collaborative notes and fireplace chats with like-minded folks. Jump to first confirmed speakers. Check schedule  →

Both days start at 8 AM PDT (check your time), with interactive sessions, followed up with a time for Q&As and discussion zones.

Ah, and the best bit: a conference in which you play an active role — taking part in live sessions, Q&As, discussion zones and challenges. To the schedule. But of course that’s not all! Be prepared for design & coding challenges, scavenger hunt and fireplace sessions with mystery guests. And to keep in style, of course we’ll throw a Smashing Party.

Do you like what you see, but are worried about getting some time off from work? Well, you surely didn’t think we would leave your hanging? We know how difficult it can sometimes be, and so we’ve prepared a neat lil’ Convince-Your-Boss template to help you out. Good luck!

3. Smashing Meets (Free)

Topple sitting next to a campfireWe’re super excited to run our very first Smashing meetup next week! We will focus on front-end and UX, but also cover all sorts of topics from performance to accessibility. Smashing Meets wouldn’t be possible without some amazing communities from around the world, so another Thank You to everyone involved!

4. Smashing TV (Free Webinar on May 19th)

Photo of Carie Fisher and Harris SchneidermanLooking for ways to help you expand your accessibility test coverage beyond automation? With very little resources, you can make a meaningful difference. Join us with Carie Fisher and Harris Schneiderman at 7:00 PM CET/1:00 PM EDT who will demonstrate the basics of automated testing and share key lessons on on maximizing your accessibility impact.

Sharing Personal Experiences And Stories

Smashing Podcast moderated by Drew McLellanWe’re moving onto our 16th episode of the Smashing Podcast next week! The Smashing Podcast is the perfect way to take a little bit of Smashing along with you on your morning walks, while washing the dishes, or anytime you like really. You can subscribe in your favorite app to get new episodes as soon as they’re ready.

Your Design Work Deserves Attention

Do you have artwork you’d love to share with the design community? If so, please do! We are always looking for creative talent, so if you have an idea for a wallpaper design, please don’t hesitate to submit it. Join in! →

We publish a new article every day on various topics that are current in the web industry. Here are some that our readers seemed to enjoy the most and have recommended further:

  • Setting TypeScript For Modern React Projects Using Webpack And Babel
    by Blessing Krofegha
    This article introduces Typescript, a superscript of JavaScript that presents the static type feature for spotting common errors as developers codes, which enhances performance, hence results in robust enterprise applications. You’ll also learn how to efficiently set up TypeScript in a React Project as we build a Money Heist Episode Picker App, exploring TypeScript, React hooks such as useReducer, useContext and Reach Router.
  • A Complete Guide To Mechanical Keyboards
    by Ben Frain
    How much thought have you put into your primary input device? Ever considered how much better your interface with your computer might be? In this article, we dive into the possibilities of mechanical keyboards. The different layouts, switch types and even keycap material. Strap yourself in — this will be a deep dive!
  • Micro-Typography: How To Space And Kern Punctuation Marks And Other Symbols
    by Thomas Bohm
    For hundreds of years, we have been using white space in typography. Today, in 2020, how do we add spacing to punctuation marks and other symbols, and how do we adjust the space on the left and right side in an easy and consistent way? It is actually not as easy and quick as it should be.
  • How To Pass Data Between Components In Vue.js
    by Matt Maribojoc
    With so many different ways to share data across components, you should know which technique is best for your situation. Let’s analyze three of the most common ways to pass data in VueJS.
  • Reducing Design Risk
    by Eric Olive
    The pressure to rush market and usability research carries risk. We’ll offer four practical techniques to mitigate this risk and create designs that better serve customers and the company: context over convenience, compromise, better design decisions, design reduction.

Best Picks From Our Newsletter

We’ll be honest: Every second week, we struggle with keeping the Smashing Newsletter issues at a moderate length — there are just so many talented folks out there working on brilliant projects! Kudos to everyone involved!

Interested in sponsoring? Feel free to check out our partnership options and get in touch with the team anytime — they’ll be sure to get back to you right away.

P.S. A huge thank you to Cosima Mielke for writing and preparing these posts!

Creating Accessible Color Palettes

Finding the perfect tint or shade of a color is not only a matter of taste but also accessibility. After all, if color contrast is lacking, a product could, in the worst case, even become unusable for people with vision impairments. A very detailed contrast checker to help you detect potential pitfalls ahead of time comes from Gianluca Gini: Geenes.

Geenes

The tool lets you tinker with hue ranges and saturation and apply the color palettes to one of three selectable UI mockups. Once applied, you can trigger different kinds of vision impairments to see how affected people see the colors and, finally, make an informed decision on the best tones for your palette. To use the colors right away, just copy and paste their code or export them to Sketch.

Command Line Love

It’s not uncommon for technical documentation to be dry and feel intimidating, especially for people who are just getting started with a new tool. That can get quite frustrating especially when a manual is difficult to read or follow, or the explanations are verbose and lack examples.

Dash Dash

Dash Dash takes the Unix (Linux, BSD, macOS) open source manual pages and sets the content in a beautiful type and layout. It provides not only explanations of all commands, but also search, examples and TL;DR sections. Also, The Art of Command Line takes you on a journey to Command Line from basics to system debugging.

And if you are up for advanced command line techniques, cmdchallenge prompts you to solve tasks with a single line of bash. (vf)

Accessible Component Libraries

While many of the component libraries we create are trying to cover all the usual suspects (the accordions, the tables, the carousels, the drop-downs, along with typography, colors and box shadows), No Style Design System by Adam Silver is focused primarily around accessibility and web forms.

Accessible Component Libraries

As a system created for and used in his book on Form Design Patterns, Adam’s library provides a set of accessible components for everything from autocomplete, checkboxes and password reveal to radios, select boxes and steppers. Most of them have a minimal CSS styling with clean, accessible markup. And if you need slightly more advanced components, Heydon Pickering’s Inclusive Components has got your back: with comprehensive tutorials on accessible cards, data tables, notifications, sliders, tabbed inerfaces, tooltips, menus and toggles. (vf)

Custom CSS Cascades

Miriam Suzanne built a demo to illustrate a very clever way to define a cascade of custom properties. One that allows you to determine which intent should take priority, without worrying about the specificity of how the value is defined.

See the Pen [Custom Cascades](https://codepen.io/smashingmag/pen/JjYawPP) by Miriam Suzanne.

See the Pen Custom Cascades by Miriam Suzanne.

Miriam shows how it works at the example of a button. Due to how the cascade is arranged, the default button is always falling back to --btn-bg--default. Adding the disabled attribute, always overrides any other button colors, no matter where they are defined, and, when new button types are created, --btn-bg--type ensures that only the defaults are overridden but not the state. The approach also lets you set these values contextually. A smart solution to avoid the usual dangers that highly-specified inline styles usually bring along.

Front-End Bookmarks

Some of us save all the useful articles and talks they come across in one ever-growing bookmark folder (which can make finding what you’re looking for quite a challenge at times), others have a more organized approach. Like Manuel Matuzović.

Front-End Bookmarks

Manuel collects articles and talks about HTML, CSS, and JavaScript on his site Front-End Bookmarks, grouped alphabetically by elements, attributes, properties, selectors, methods, and expressions. No matter if you’re looking for information on how to correctly use aria-labelledby or what the ::marker pseudo-element is all about, chances are good that Manuel already compiled helpful resources on the topic. By the way, if you feel that a resource is missing in the collection, don’t hesitate to contribute to it on GitHub.

GitHub Tips And Tricks

Do you know how to automatically squash commits on GitHub when merging pull requests? Or how to open a repo in the browser using GitHub CLI? If not, Joe Previte’s collection of GitHub tips and tricks might be for you.

GitHub Tips And Tricks

In bite-sized videos, Joe shares small but powerful tips to take your GitHub workflow to the next level. And for those of you who prefer to learn by reading, most tips are also available as short blog posts. Handy little timesavers.

The Sound Of Colleagues

Working from home can have some real advantages over working from an office, but let’s be honest, it can be a rather lonely experience, too, when there are no colleagues around. If you feel your home office is getting too quiet and you need some bustle in the background to stay focused, The Sound of Colleagues has got your back.

The Sound Of Colleagues

The Sound of Colleagues lets you mix office noises to create your custom office ambient noise. People typing and talking, phones ringing, the coffee machine, the printer — all of these little things add up to bring a bit of office feeling to your home. Maybe it’ll even help you boost your productivity, who knows?

A Minimalist And Modern Media Player Library

If you want to embed a media player on your site, Vime might be worth taking a closer look at. Built around the idea that you control the player, not the other way around, the open-source library provides an alternative to Videojs and Plyr and supports HTML5, HLS, Dash, YouTube, Vimeo, and Dailymotion.

Vime

Vime does not only shine with a minimalist, sleek look, but it is responsive, accessible, modular, and lightweight, too. It gets by without any external dependencies and comes in different packages tailored to different needs so that you can pick just what’s required for your use case. And since minimalist doesn’t mean bland, Vime is backed up by a plugin system that offers a lot of room for customization — think custom controls, settings, tooltips, and more. The last two versions of all modern browsers as well as IE11 are supported.

Smashing Editorial (cm, vf, ra)

An Interview With Zach Leatherman: A SmashingConf Austin Speaker

An Interview With Zach Leatherman: A SmashingConf Austin Speaker

An Interview With Zach Leatherman: A SmashingConf Austin Speaker

Rachel Andrew

We are so excited to be bringing SmashingConf to a new city this year. We’re bringing you SmashingConf Austin and we have a fantastic line-up of speakers.

Check out this post, where we introduce our new venue of Austin and share an interview with Miriam Suzanne. This time we have an interview with Zach Leatherman.

Zach will be talking about type and font performance at SmashingConf Austin. See you there?

Zach is no stranger to the Smashing stage, and if you want to find out more about web fonts and loading strategies, you can watch his talk from SmashingConf London 2018, paired with a talk by Monica Dinculescu from SmashingConf Barcelona, “Web Fonts And Performance: SmashingConf Videos".

Also, take a look at some of the resources that Zach has made available on the subject in his archive of posts about web fonts. There is plenty to get you started, and I think you can agree that there is no-one better to help us understand the current state of font loading while we are in Austin!

Tickets Are On Sale Now!

If you want to join in the fun, tickets are on sale. Last year, we sold out three of our conferences well before the conference date, and popular workshops also fill up fast. Just saying!

Smashing Editorial (il)

Link Underlines That Animate Into Block Backgrounds

It's a cool little effect. The default link style has an underline (which is a good idea) and then on :hover you see the underline essentially thicken up turning into almost what it would have looked liked if you used a background-color on the link instead.

Here's an example of the effect on the Superfriendly site:

A journey:

  • The Superfriendly site does it with box-shadow. Turning box-shadow: inset 0 -0.07em 0 #0078d6; into box-shadow: inset 0 -0.85em 0 #a2d5fe; with a transition. Andres Cuervo ported that idea to a Pen. (I forked it to fix the "start offset" idea that was broken-seeming to me on the original).
  • You might be tempted to draw the line with a pseudo-element that's, say, absolutely positioned within the relatively positioned link. Then you animate its height or scaleY or something. Here's that kind of idea. Your enemy here is going to be links that break onto new lines, which box-shadow seems to handle more elegantly.
  • Another idea would be using linear-gradient with hard color stops to kinda "fake" the drawing of a line that's positioned to look like an underline. Then the gradient can be animated to cover the element on hover, probably by moving its background-position. Here's that kind of idea and another example we wrote up a little while back. This handles line breaks nicer than the previous method.
  • The default text-decoration: underline; has a distinct advantage these days: text-decoration-skip-ink! It has become the default behavior for links to have the underlines deftly skip around the decenders in text, making for much nicer looking underlines than any of these techniques (also: borders) can pull off. There are properties that are somewhat new that you may not be aware of that give you more control over the underline that we have traditionally had, like text-decoration-color. But there is more, like thickness and offset, that make this effect possible! Miriam Suzanne has a demo of exactly this, which only works in Firefox Nightly at the moment, but should be making the rounds soon enough.

Summary: If you need to do this effect right now in the most browsers you can, the box-shadow technique is probably best. If it's just an enhancement that can wait a bit, using text-decoration-thickness / text-decoration-offset / text-decoration-color with a transition is a better option for aesthetics, control, and being able to understand the code at first glance.

The post Link Underlines That Animate Into Block Backgrounds appeared first on CSS-Tricks.

CSS Custom Properties In The Cascade

CSS Custom Properties In The Cascade

CSS Custom Properties In The Cascade

Miriam Suzanne

Last month, I had a conversation on Twitter about the difference between “scoped” styles (generated in a build process) and “nested” styles native to CSS. I asked why, anecdotally, developers avoid the specificity of ID selectors, while embracing “scoped styles” generated by JavaScript? Keith Grant suggested that the difference lies in balancing the cascade* and inheritance, i.e. giving preference to proximity over specificity. Let’s take a look.

The Cascade

The CSS cascade is based on three factors:

  1. Importance defined by the !important flag, and style origin (user > author > browser)
  2. Specificity of the selectors used (inline > ID > class > element)
  3. Source Order of the code itself (latest takes precedence)

Proximity is not mentioned anywhere — the DOM-tree relationship between parts of a selector. The paragraphs below will both be red, even though #inner p describes a closer relationship than #outer p for the second paragraph:

See the Pen [Cascade: Specificity vs Proximity](https://codepen.io/smashingmag/pen/OexweJ/) by Miriam Suzanne.

See the Pen Cascade: Specificity vs Proximity by Miriam Suzanne.
<section id="outer">
  <p>This text is red</p>
  <div id="inner">
    <p>This text is also red!</p>
  </div>
</section>
#inner p {
  color: green;
}

#outer p {
  color: red;
}

Both selectors have the same specificity, they are both describing the same p element, and neither is flagged as !important — so the result is based on source-order alone.

BEM And Scoped Styles

Naming conventions like BEM (“Block__Element—Modifier”) are used to ensure that each paragraph is “scoped” to only one parent, avoiding the cascade entirely. Paragraph “elements” are given unique classes specific to their “block” context:

See the Pen [BEM Selectors & Proximity](https://codepen.io/smashingmag/pen/qzPyeM/) by Miriam Suzanne.

See the Pen BEM Selectors & Proximity by Miriam Suzanne.
<section class="outer">
  <p class="outer__p">This text is red</p>
  <div class="inner">
    <p class="inner__p">This text is green!</p>
  </div>
</section>
.inner__p {
  color: green;
}

.outer__p {
  color: red;
}

These selectors still have the same relative importance, specificity, and source order — but the results are different. “Scoped” or “modular” CSS tools automate that process, re-writing our CSS for us, based on the HTML. In the code below, each paragraph is scoped to its direct parent:

See the Pen [Scoped Style Proximity](https://codepen.io/smashingmag/pen/NZaLWN/) by Miriam Suzanne.

See the Pen Scoped Style Proximity by Miriam Suzanne.
<section outer-scope>
  <p outer-scope>This text is red</p>
  <div outer-scope inner-scope>
    <p inner-scope>This text is green!</p>
  </div>
</section>
p[inner-scope] {
  color: green
}

p[outer-scope] {
  color: red;
}

Inheritance

Proximity is not part of the cascade, but it is part of CSS. That’s where inheritance becomes important. If we drop the p from our selectors, each paragraph will inherit a color from its closest ancestor:

See the Pen [Inheritance: Specificity vs Proximity](https://codepen.io/smashingmag/pen/mZBGyN/) by Miriam Suzanne.

See the Pen Inheritance: Specificity vs Proximity by Miriam Suzanne.
#inner {
  color: green;
}

#outer {
  color: red;
}

Since #inner and #outer describe different elements, our div and section respectively, both color properties are applied without conflict. The nested p element has no color specified, so the results are determined by inheritance (the color of the direct parent) rather than cascade. Proximity takes precedence, and the #inner value overrides the #outer.

But there’s a problem: In order to use inheritance, we are styling everything inside our section and div. We want to target the paragraph color specifically.

(Re-)Introducing Custom Properties

Custom properties provide a new, browser-native solution; they inherit like any other property, but they don’t have to be used where they are defined. Using plain CSS, without any naming conventions or build tools, we can create a style that is both targeted and contextual, with proximity taking precedence over the cascade:

See the Pen [Custom Props: Specificity vs Proximity](https://codepen.io/smashingmag/pen/gNGdaO/) by Miriam Suzanne.

See the Pen Custom Props: Specificity vs Proximity by Miriam Suzanne.
p {
  color: var(--paragraph);
}

#inner {
  --paragraph: green;
}

#outer {
  --paragraph: red;
}

The custom --paragraph property inherits just like the color property, but now we have control over exactly how and where that value is applied. The --paragraph property acts similar to a parameter that can be passed into the p component, either through direct selection (specificity-rules) or context (proximity-rules).

I think this reveals a potential for custom properties that we often associate with functions, mixins, or components.

Custom “Functions” And Parameters

Functions, mixins, and components are all based on the same idea: reusable code, that can be run with various input parameters to get consistent-but-configurable results. The distinction is in what they do with the results. We’ll start with a striped-gradient variable, and then we can extend it into other forms:

html {
  --stripes: linear-gradient(
    to right,
    powderblue 20%, pink 20% 40%, white 40% 60%, pink 60% 80%, powderblue 80%
  );
}

That variable is defined on the root html element (could also use :root, but that adds unnecessary specificity), so our striped variable will be available everywhere in the document. We can apply it anywhere gradients are supported:

See the Pen [Custom Props: Variable](https://codepen.io/smashingmag/pen/NZwrrm/) by Miriam Suzanne.

See the Pen Custom Props: Variable by Miriam Suzanne.
body {
  background-image: var(--stripes);
}

Adding Parameters

Functions are used like variables, but define parameters for changing the output. We can update our --stripes variable to be more function-like by defining some parameter-like variables inside it. I’ll start by replacing to right with var(--stripes-angle), to create an angle-changing parameter:

html {
  --stripes: linear-gradient(
    var(--stripes-angle),
    powderblue 20%, pink 20% 40%, white 40% 60%, pink 60% 80%, powderblue 80%
  );
}

There are other parameters we could create, depending on what purpose the function is meant to serve. Should we allow users to pick their own stripe colors? If so, does our function accept 5 different color parameters or only 3 that will go outside-in like we have now? Do we want to create parameters for color-stops as well? Every parameter we add provides more customization at the cost of simplicity and consistency.

There is no universal right answer to that balance — some functions need to be more flexible, and others need to be more opinionated. Abstractions exist to provide consistency and readability in your code, so take a step back and ask what your goals are. What really needs to be customizable, and where should consistency be enforced? In some cases, it might be more helpful to have two opinionated functions, rather than one fully-customizable function.

To use the function above, we need to pass in a value for the --stripes-angle parameter, and apply the output to a CSS output property, like background-image:

/* in addition to the code above… */
html {
  --stripes-angle: 75deg;
  background-image: var(--stripes);
}

See the Pen [Custom Props: Function](https://codepen.io/smashingmag/pen/BgwOjj/) by Miriam Suzanne.

See the Pen Custom Props: Function by Miriam Suzanne.

Inherited Versus Universal

I defined the --stripes function on the html element out of habit. Custom properties inherit, and I want my function available everywhere, so it makes some sense to put it on the root element. That works well for inheriting variables like --brand-color: blue, so we might also expect it to work for our “function” as well. But if we try to use this function again on a nested selector, it won’t work:

See the Pen [Custom Props: Function Inheritance Fail](https://codepen.io/smashingmag/pen/RzjRrM/) by Miriam Suzanne.

See the Pen Custom Props: Function Inheritance Fail by Miriam Suzanne.
div {
  --stripes-angle: 90deg;
  background-image: var(--stripes);
}

The new --stripes-angle is ignored entirely. It turns out we can’t rely on inheritance for functions that need to be re-calculated. That’s because each property value is computed once per element (in our case, the html root element), and then the computed value is inherited. By defining our function at the document root, we don’t make the entire function available to descendants — only the computed result of our function.

That makes sense if you frame it in terms of the cascading --stripes-angle parameter. Like any inherited CSS property, it is available to descendants but not ancestors. The value we set on a nested div is not available to a function we defined on the html root ancestor. In order to create a universally-available function that will re-calculate on any element, we have to define it on every element:

See the Pen [Custom Props: Universal Function](https://codepen.io/smashingmag/pen/agLaNj/) by Miriam Suzanne.

See the Pen Custom Props: Universal Function by Miriam Suzanne.
* {
  --stripes: linear-gradient(
    var(--stripes-angle),
    powderblue 20%, pink 20% 40%, white 40% 60%, pink 60% 80%, powderblue 80%
  );
}

The universal selector makes our function available everywhere, but we can define it more narrowly if we want. The important thing is that it can only re-calculate where it is explicitly defined. Here are some alternatives:

/* make the function available to elements with a given selector */
.stripes { --stripes: /* etc… */; } 

/* make the function available to elements nested inside a given selector */
.stripes * { --stripes: /* etc… */; } 

/* make the function available to siblings following a given selector */
.stripes ~ * { --stripes: /* etc… */; } 

See the Pen [Custom Props: Scoped Function](https://codepen.io/smashingmag/pen/JQMvGM/) by Miriam Suzanne.

See the Pen Custom Props: Scoped Function by Miriam Suzanne.

This can be extended with any selector logic that doesn’t rely on inheritance.

Free Parameters And Fallback Values

In our example above, var(--stripes-angle) has no value and no fallback. Unlike Sass or JS variables that must be defined or instantiated before they are called, CSS custom properties can be called without ever being defined. This creates a “free” variable, similar to a function parameter that can be inherited from the context.

We can eventually define the variable on html or :root (or any other ancestor) to set an inherited value, but first we need to consider the fallback if no value is defined. There are several options, depending on exactly what behavior we want

  1. For “required” parameters, we don’t want a fallback. As-is, the function will do nothing until --stripes-angle is defined.
  2. For “optional” parameters, we can provide a fallback value in the var() function. After the variable-name, we add a comma, followed by the default value:
var(--stripes-angle, 90deg)

Each var() function can only have one fallback — so any additional commas will be part of that value. That makes it possible to provide complex defaults with internal commas:

html {
  /* Computed: Hevetica, Ariel, sans-serif */
  font-family: var(--sans-family, Hevetica, Ariel, sans-serif);

  /* Computed: 0 -1px 0 white, 0 1px 0 black */
  test-shadow: var(--shadow, 0 -1px 0 white, 0 1px 0 black);
} 

We can also use nested variables to create our own cascade rules, giving different priorities to the different values:

var(--stripes-angle, var(--global-default-angle, 90deg))
  1. First, try our explicit parameter (--stripes-angle);
  2. Fallback to a global “user default” (--user-default-angle) if it’s available;
  3. Finally, fallback to our “factory default” (90deg).

See the Pen [Custom Props: Fallback Values](https://codepen.io/smashingmag/pen/jjGvVm/) by Miriam Suzanne.

See the Pen Custom Props: Fallback Values by Miriam Suzanne.

By setting fallback values in var() rather than defining the custom property explicitly, we ensure that there are no specificity or cascade restrictions on the parameter. All the *-angle parameters are “free” to be inherited from any context.

Browser Fallbacks Versus Variable Fallbacks

When we’re using variables, there are two fallback paths we need to keep in mind:

  1. What value should be used by browsers without variable support?
  2. What value should be used by browsers that support variables, when a particular variable is missing or invalid?
p {
  color: blue;
  color: var(--paragraph);
}

While old browsers will ignore the variable declaration property, and fallback to blue — modern browsers will read both and use the latter. Our var(--paragraph) might not be defined, but it is valid and will override the previous property, so browsers with variable support will fallback to the inherited or initial value, as if using the unset keyword.

That may seem confusing at first, but there are good reasons for it. The first is technical: browser engines handle invalid or unknown syntax at “parse time” (which happens first), but variables are not resolved until “computed-value time” (which happens later).

  1. At parse time, declarations with invalid syntax are ignored completely — falling back on earlier declarations. This is the path that old browsers will follow. Modern browsers support the variable syntax, so the previous declaration is discarded instead.
  2. At computed-value time the variable is compiled as invalid, but it’s too late — the previous declaration was already discarded. According to the spec, invalid variable values are treated the same as unset:

See the Pen [Custom Props: Invalid/Unsupported vs Undefined](https://codepen.io/smashingmag/pen/VJMGbJ/) by Miriam Suzanne.

See the Pen Custom Props: Invalid/Unsupported vs Undefined by Miriam Suzanne.
html {
  color: red;
  
  /* ignored as *invalid syntax* by all browsers */
  /* - old browsers: red */
  /* - new browsers: red */
  color: not a valid color; 
  color: var(not a valid variable name); 
  
  /* ignored as *invalid syntax* by browsers without var support */
  /* valid syntax, but invalid *values* in modern browsers */
  /* - old browsers: red */
  /* - new browsers: unset (black) */
  --invalid-value: not a valid color value;
  color: var(--undefined-variable);
  color: var(--invalid-value);
}

This is also good for us as authors, because it allows us to play with more complex fallbacks for the browsers that support variables, and provide simple fallbacks for older browsers. Even better, that allows us to use the null/undefined state to set required parameters. This becomes especially important if we want to turn a function into a mixin or component.

Custom Property “Mixins”

In Sass, the functions return raw values, while mixins generally return actual CSS output with property-value pairs. When we define a universal --stripes property, without applying it to any visual output, the result is function-like. We can make that behave more like a mixin, by defining the output universally as well:

* {
  --stripes: linear-gradient(
    var(--stripes-angle),
    powderblue 20%, pink 20% 40%, white 40% 60%, pink 60% 80%, powderblue 80%
  );
  background-image: var(--stripes);
}

As long as --stripes-angle remains invalid or undefined, the mixin fails to compile, and no background-image will be applied. If we set a valid angle on any element, the function will compute and give us a background:

div {
  --stripes-angle: 30deg; /* generates the background */
}

Unfortunately, that parameter-value will inherit, so the current definition creates a background on the div and all descendants. To fix that, we have to make sure the --stripes-angle value doesn’t inherit, by resting it to initial (or any invalid value) on every element. We can do that on the same universal selector:

See the Pen [Custom Props: Mixin](https://codepen.io/smashingmag/pen/ZdXMJx/) by Miriam Suzanne.

See the Pen Custom Props: Mixin by Miriam Suzanne.
* {
  --stripes-angle: initial;
  --stripes: /* etc… */;
  background-image: var(--stripes);
}

Safe Inline Styles

In some cases, we need the parameter to be set dynamically from outside CSS — based on data from a back-end server or front-end framework. With custom properties, we can safely define variables in our HTML without worrying about the usual specificity issues:

See the Pen [Custom Props: Mixin + Inline Style](https://codepen.io/smashingmag/pen/qzPMPv/) by Miriam Suzanne.

See the Pen Custom Props: Mixin + Inline Style by Miriam Suzanne.
<div style="--stripes-angle: 30deg">...</div>

Inline styles have a high specificity, and are very hard to override — but with custom properties, we we have another option: ignore it. If we set the div to background-image: none (for example) that inline variable will have no impact. To take it even farther, we can create an intermediate variable:

* { --stripes-angle: var(--stripes-angle-dynamic, initial); }

Now we have the option to define --stripes-angle-dynamic in the HTML, or ignore it, and set --stripes-angle directly in our stylesheet.

See the Pen [Custom Props: Mixin + Inline / Override](https://codepen.io/smashingmag/pen/ZdXMao/) by Miriam Suzanne.

See the Pen Custom Props: Mixin + Inline / Override by Miriam Suzanne.

Preset Values

For more complex values, or common patterns we want to re-use, we can also provide a few preset variables to choose from:

* {
  --tilt-down: 6deg;
  --tilt-up: -6deg;
}

And use those presets, rather than setting the value directly:

<div style="--stripes-angle: var(--tilt-down)">...</div>

See the Pen [Custom Props: Mixin + Presets](https://codepen.io/smashingmag/pen/LKemZm/) by Miriam Suzanne.

See the Pen Custom Props: Mixin + Presets by Miriam Suzanne.

This is great for creating charts and graphs based on dynamic data, or even laying out a day planner.

See the Pen [Bar chart in CSS grid + variables](https://codepen.io/smashingmag/pen/wLrEyg/) by Miriam Suzanne.

See the Pen Bar chart in CSS grid + variables by Miriam Suzanne.

Contextual Components

We can also re-frame our “mixin” as a “component” by applying it to an explicit selector, and making the parameters optional. Rather than relying on the presence-or-absence of --stripes-angle to toggle our output, we can rely on the presence-or-absence of a component selector. That allows us to set fallback values safely:

See the Pen [Custom Props: Component](https://codepen.io/smashingmag/pen/QXqVmM/) by Miriam Suzanne.

See the Pen Custom Props: Component by Miriam Suzanne.
[data-stripes] {
  --stripes: linear-gradient(
    var(--stripes-angle, to right),
    powderblue 20%, pink 20% 40%, white 40% 60%, pink 60% 80%, powderblue 80%
  );
  background-image: var(--stripes);
}

By putting the fallback inside the var() function, we can leave --stripes-angle undefined and “free” to inherit a value from outside the component. This is a great way to expose certain aspects of a component style to contextual input. Even “scoped” styles generated by a JS framework (or scoped inside the shadow-DOM, like SVG icons) can use this approach to expose specific parameters for outside influence.

Isolated Components

If we don’t want to expose the parameter for inheritance, we can define the variable with a default value:

[data-stripes] {
  --stripes-angle: to right;
  --stripes: linear-gradient(
    var(--stripes-angle, to right),
    powderblue 20%, pink 20% 40%, white 40% 60%, pink 60% 80%, powderblue 80%
  );
  background-image: var(--stripes);
}

These components would also work with a class, or any other valid selector, but I chose the data-attribute to create a namespace for any modifiers we want:

[data-stripes='vertical'] { --stripes-angle: to bottom; }
[data-stripes='horizontal'] { --stripes-angle: to right; }
[data-stripes='corners'] { --stripes-angle: to bottom right; }

See the Pen [Custom Props: Isolated Components](https://codepen.io/smashingmag/pen/agLaGX/) by Miriam Suzanne.

See the Pen Custom Props: Isolated Components by Miriam Suzanne.

Selectors and Parameters

I often wish I could use data-attributes to set a variable — a feature supported by the CSS3 attr() specification, but not yet implemented in any browsers (see the resources tab for linked issues on each browser). That would allow us to more closely associate a selector with a particular parameter:

<div data-stripes="30deg">...</div>


/* Part of the CSS3 spec, but not yet supported */
/* attr( , ) */
[data-stripes] {
  --stripes-angle: attr(data-stripes angle, to right);
}

In the meantime, we can achieve something similar by using the style attribute:

See the Pen [Custom Props: Style Selectors](https://codepen.io/smashingmag/pen/PrJdBG/) by Miriam Suzanne.

See the Pen Custom Props: Style Selectors by Miriam Suzanne.
<div style="--stripes-angle: 30deg">...</div>


/* The `*=` atttribute selector will match a string anywhere in the attribute */
[style*='--stripes-angle'] {
  /* Only define the function where we want to call it */
  --stripes: linear-gradient(…);  
}

This approach is most useful when we want to include other properties in addition to the parameter being set. For example, setting a grid area could also add padding and background:

[style*='--grid-area'] {
  background-color: white;
  grid-area: var(--grid-area, auto / 1 / auto / -1);
  padding: 1em;
}

Conclusion

When we start to put all these pieces together, it becomes clear that custom properties go far beyond the common variable use-cases we’re familiar with. We’re not only able to store values, and scope them to the cascade — but we can use them to manipulate the cascade in new ways, and create smarter components directly in CSS.

This calls for us to re-think many of the tools we’ve relied on in the past — from naming conventions like SMACSS and BEM, to “scoped” styles and CSS-in-JS. Many of those tools help work around specificity, or manage dynamic styles in another language — use-cases that we can now address directly with custom properties. Dynamic styles that we’ve often calculated in JS, can now be handled by passing raw data into the CSS.

At first, these changes may be seen as “added complexity” — since we’re not used to seeing logic inside CSS. And, as with all code, over-engineering can be a real danger. But I’d argue that in many cases, we can use this power not to add complexity, but to move complexity out of third-party tools and conventions, back into the core language of web design, and (more importantly) back into the browser. If our styles require calculation, that calculation ought to live inside our CSS.

All of these ideas can be taken much further. Custom properties are just starting to see wider adoption, and we’ve only begun to scratch the surface of what’s possible. I’m excited to see where this goes, and what else people come up with. Have fun!

Further Reading

Smashing Editorial (dm, il)