468: Is Sass Still Cool? Animation vs Transition, Animated Tables, and Dark Mode in Email
Let's talk Sass, nesting, animation vs transition, animated tables, scroll snap points, progress meters, viewing emails in dark mode, and coded prototypes.
Chris Coyier and Dave Rupert
Time Jump Links
MANTRA: Just Build Websites!
Dave Rupert: Oh, it's recording. Okay. [Laughter]
Hey there, Shop-o-maniacs. You're listening to another episode of the ShopTalk Show, a podcast all about front-end Web design and development. I'm Dave Rupert and with me is Chris Coyier. Hey, Chris, how are you?
Chris Coyier: Hey! Good. Good. Good. Good. Good. Yeah. Relatively, anyway. You know there's always something. When you're old, it's just like one part of your body breaks and then you just struggle to fix it. And right at the end of recovery, something else breaks.
Chris: That's the rule.
Dave: It's the wheel of maladies. You just wake up every morning, you spin it, and you know something hurts.
Chris: Yeah. I saw this meme of this woman kneeling and she's like, "Woman's knee hurts for the rest of her life because she kneeled awkwardly for two minutes."
Dave: [Laughter] Basically. I've been having -- I think I'm allergic to mold or sensitive to pressure, like in the atmosphere. You know? Man, if it is going to rain (in the forecast) like three days out, I have migraines. It's to the point I need to lay down and take a nappy-nap.
You know, and so you're just like, "How do you fix the sky? The sky is making me sick. How do I fix that?" You know? It's not easy. Everything is like, "Drink water." [Laughter] Okay, dude. Yeah, I got water figured out. So, anyway. I'm sure I'm fine, but it's just so weird how even your body changes over time.
Decades, I was fine. It could rain and I would be fine. But now, apparently, the sky hurts me, so.
Chris: [Laughter] Sorry, man.
Dave: Oh, well.
Chris: Yes, it does.
Chris: Everything hurts.
Dave: That's why - indoors.
Dave: See, outdoors--
Chris: Should I change our--?
Dave: Yeah, people love outdoors.
Chris: --our topic?
Dave: Yeah, and indoors is good. So, there you go.
Chris: I always remember that. What was it? Hot American Summer, and it was Paul Rudd. No, who was it? It was that nerd, David, who came in and he was trying to describe the kid he was looking for. He was like, "No, he's more of a [stutters]... He's an indoor kid." [Laughter]
Dave: Yeah, he's an indoor kid.
Chris: Indoor kid. I should get an indoor kid T-shirt.
Chris: Although, I like the outside too. [Laughter]
Dave: I do. I do like outside. It just hurts me. That's all.
Chris: [Laughter] Well, we mentioned Astro last week. Sorry if we took... We won't do that to you this week, but I did note that it's interesting how many styling options there are in it.
Chris: You can just put a style tag in your component and it will scope it. But if you want to style some other way, you can. They have a whole piece of docs on all the different styling options they support. It's pretty sweet.
One of them, you can just type lang=scss on your style block and then just write in Sass. It just ships with it out of the block. Can you believe it?
2021, everybody still likes Sass. There's a little conversation about it in the Discord, too. Literally, everybody likes Sass. I've never seen a dev ever that's just like, "Sass sucked. I like something else instead." I mean some people like other things too, but nobody is anti-Sass. It's kind of funny.
Dave: I've seen a few, but I think they're just - whatever - contrarian for headlines, you know.
Dave: But you know.
Chris: Fair enough. Or I like writing vanilla CSS. Fair enough. That's totally fine. It doesn't make Sass suck. You know?
Chris: Moving away from Sass is fine, too. But it's interesting how it's kind of become this expectation. There have been all kinds of tools that if they ultimately allow you to write in the CSS syntax, they tend to jam Sass into it too because why not. You can run that processor too. In this world where we're just kind of daisy-chaining processors together [laughter]--
Chris: That seems kind of fine. I wonder, though. Is it a forever project? I think we've probably talked about this before, but it's curious how long it's held on and why.
Some people are like, "I just like concatenating my files together." Well, sure. Fair enough. It happens to be a tool that does that. That's their big one. I know I like nesting media queries. That's a big one, but I like nesting, period, as long as you're careful with it. Some people are pretty hot on the idea of how they handle variables because it's not just a variable but it can be objective variables.
Dave: Mm-hmm. Mm-hmm.
Chris: Like a map. That's kind of cool. Everybody has got their things, so I was just curious, you know, like, what will be the spear in Sass's heart, or will there never be because Sass is still an active project and can evolve and solve new problems if we need it to?
Dave: Yeah. What I reach for goes down every day, it feels like. CSS Custom Properties, I actually maybe am getting to the point where I prefer them to Sass variables. I would actually rather be using those.
I know the second you say that, 400 people show up at your door and say, "Oh, but it doesn't work in IE, and I can't use it." you know?
Dave: That's true, and I'm sorry that happened to you. However, in a year or two, you'll be in a different boat - probably. I hope so.
Chris: Yeah. They are so good, though, aren't they? They really do. There's very little where I'm like, "Ah, I wish I was using Sass here," because they're twice as capable.
Dave: Yeah. Well, and so I'm authoring scope styles in Nuxt, like as a day job. [Laughter]
Dave: It's great. I love scope styles, and it supports Sass, so I can just the smidge of nesting, and that makes my component, because I'm writing a component.
Chris: Exactly. Oh, I love that.
Dave: And I'm doing nesting. It's fricken' beautiful right up until I have to go import assets, variables. I have to go import the Sass file and the functions file and the everything.
Chris: Oh, I see.
Dave: Just to write a variable. So, now I've got--
Chris: Then you have to teach your compiler how to do those imports? Is that -- has that bothered you?
Dave: Yeah. Well, Sass sort of figures it out because variables, in theory, are just translucent. They don't output any style.
Dave: The component knows how. The Sass processor at the component level knows how to do that. If it was something I needed, like the button styles or something like that, that might be a little bit more complex.
Chris: Are you actually writing @import or are you writing @use?
Dave: I'm using @import, but @use would definitely be the cool thing because @use tries to create an import/export tree that's tree shakable, right? That's how I understand it. Right?
Chris: Yeah. I think it's just better always.
Chris: Yeah. Yeah, I should probably use it, but you know I'm old, so it's hard to learn new things. That's not what I immediately go for.
But the moment I have to use a Sass variable in my Vue template, that's where it feels kludgy, and so that's where I'm like, "Oh, man. If I just had stickin' whatchamacallit."
Dave: If I just had variables. That encourages me to actually go and spit out custom CSS variables, as well as my Sass variables.
Chris: That's where we're at. We just do them both and they're named exactly the same.
Chris: Other than obviously the dash dash versus dollar sign. We just have two sets, and you can use either one that you want.
We're in a weird state where it's kind of 50/50, and I'm like, "Hmm. I wonder if at some point we should go clean that up," or whatever. At the moment, it's not bothering me that much, but there are moments where -- because we write in -- you're in Nuxt. I mostly write in React. There's a way to set it. If you're in JSX and you don't feel like making a class name and writing CSS for a thing that you can just do style= and just blast some inline styles on things, which really doesn't bother me that much when it's just a quick little one-off kind of thing. It just is fine.
But if it's a color that you're having to set or a background or a border, guess what. You can do it now because you have those variables available. You don't have your Sass variables there but you do have custom properties there.
Dave: If for some weird reason your component needs a black border instead of a CCC border, it's immediately better.
Dave: You know what I mean? You just say all the borders in here are--
Chris: That's great.
Dave: --you know, 000 instead of CCC. That's powerful. They were confusing when they came out, but now that it's there, it's like, this is great. This is wonderful.
Chris: Yeah. They've settled in. There were a couple of things that people tried to find that were like, "What's better about Sass variables?" Math is maybe a little easier because you don't have to calc wrap them and it's a little more forgiving in Sass what you can multiply and stuff, but it's not enough. It's not compelling enough just to use it just for that. There is always some other way you can do it.
Chris: That's that. I was thinking of nesting as a big one, though. That's why I would. If I was in something that I didn't need to bother about concatenating files because I'm writing in some component language anyway and that's just not a thing I need to worry about or do, then what I want is the nesting. That's the thing that feels like it's going to die at some point because we'll get native nesting. One we have native nesting, which is in zero browsers, but there is a pretty advanced spec on it and interest in getting it going, it's not so bad.
I remember the very, very early days when it was talked about. You'd have to prefix every nested thing with some big @nest rule. It just looked way kludgier than Sass. I think the gut reaction was -- or Less or Stylus or anything. They all do nesting (as far as I know) exactly the same.
Chris: It just looks good. It just looks intuitive and simple and there's no extra syntax you need. Native nesting has evolved to that, pretty much. I think you still need to use an ampersand situation at the front, but it's one character, and it's really....
Then you can even move the ampersand around a little bit. If you want to do something really weird, like put the ampersand in between two other selectors, which is some niche stuff, you still can but then you use the @nest rule.
Chris: We talked about this a little bit on the Adam Argyle episode - or whatever.
Chris: But now I look at the spec. I'm like, "Dude, when this drops, it's going to be rough for Sass because I'll use it less in something like a Vue component, an Astro component, or something." I'd rather just use native nesting.
Dave: Yeah. No, one less thing, right?
Chris: One less thing.
Dave: Then you just kind of assume maybe some PostCSS process is going to come through and nudge it a bit to make it a little bit more accessible for other browsers.
Dave: Well, see. Hey.
[Banjo music starts]
Chris: This episode of ShopTalk Show is brought to you in part by CMS Hub by HubSpot. Maybe you know HubSpot as a CRM. It is that. It has a bunch of different hubs, you know, hence HubSpot. [Laughter]
There's a marketing hub, meaning lead generation and automated marketing type stuff. A sales hub, which is the CRM, which does stuff like schedules meetings with your leads and provides quotes and stuff.
They have other hubs, but CMS hub is what we're talking about. It's a content management software that's super flexible. You can build whatever you want on it. In fact, it's like any other CMS. You work locally using whatever tools you want and then deploy to HubSpot, so it's your host and it's a framework for content.
What's cool is that the CMS part of it is tied to the CRM parts of it, meaning that you can build a website that people log into and use in that way, but then you are also customizing it. Because you know who they are, the fact that they're a lead, and you know information about them, you can customize the website around that. That's pretty darn cool.
This is an interesting example, I think. They have a real estate site where normally you think of a CRM as people in the CRM. But in this case, properties are the things in the CRM, so like 123 Elm Street - or whatever. That way the website (powered by CMS Hub) is grabbing that CRM data and making a website of real estate listings. But the real estate listings are in the CRM, so you're gathering leads on it like Julie wants to go see the property at 123 Elm Street. I think that's just a really cool and interesting idea.
It's loaded with other built-in features. This is pretty advanced-style hosting. They have serverless functions, for example, which is a pretty modern, cool idea that I use all the time. It has membership management in there. Again, these are websites you log into, not just like brochure sites or whatever.
There's search built in, for example. You don't have to reach for some third-party search. They've got search handled for you with it.
That's all I'll tell you for now. That's CMS Hub by HubSpot. Thanks for the support.
[Banjo music stops]
Chris: Here's a topic for you. I had Una and Andy Bell on from--
Chris: Una is at Google, you know.
Chris: And does a podcast with Adam. What did they just call it? The CSS podcast, I guess.
Dave: CSS podcast. Yes.
Chris: Yeah, pretty cool, but it's very, like, educational. Not that this show isn't. You should be learning a lot from ShopTalk - very much.
Dave: [Laughter] What do you mean? No--
Chris: Theirs is just like, "We're going to talk about the box model. Here we go."
Dave: Yeah. Yeah. Very topic-centric.
Chris: Yeah. [Laughter] Una pitched to Google, like, "Let's make a course," essentially, a CSS learning thing that they launched -- I don't know -- a couple of weeks ago now.
Chris: Learn CSS. I'm sure if you Google it, you'll land right there. It has these 23 modules of learning. Twenty-two, I guess, if you chop off the front and bottom intro and conclusion.
Chris: That covers all kinds of stuff about CSS, pretty much all of CSS, with a very modern feel to it, not like, "Here's a bunch of old stuff and we'll slap the new stuff on the end," kind of thing. It's all very like, "This is where CSS is right now." It's super well done. Love it.
They hilariously just forgot to do transitions. [Laughter]
Dave: Okay. Well--
Chris: It's just not one of them on there. They're going to add it, I think, but it's just kind of one of those funny things that even these great projects sometimes just do weird things.
Dave: Oops. Forgot it. Yeah.
Chris: But it made me think about, either of the two that should be on a course like this -- and this is not criticism. I don't really care. But it maybe -- animations made the cut and transitions didn't. Not that they weighed them up and made the choice that way, but I'm like, I occasionally write a keyframe and I occasionally do it almost for trickery sometimes because I need it to apply. It's something that a transition can't do. But 94% of the time, in my CSS, it's a transition. When I say CSS animation, I sometimes basically just mean a transition because it's movement and the word animation evokes movement.
Chris: That's what I meant even though I said the word animation. [Laughter] You know?
Dave: Right. Right.
Chris: Anyway, my point is, is that true for you too? Do you write mostly transitions or am I weird?
Dave: No, that's a good question. I think I do or I try to write transitions just because they're cheap. You know?
My new thing is when you click a button, maybe it grows a bit. Like, pew, like a pop, you know?
Chris: Sure. Yeah.
Dave: Like a juicy button, we'll call them.
Dave: Juiciness, that's what's it's called in video game land, like where you just screen shake and do all this stuff.
Chris: Is it?
Dave: Yeah, it's called juiciness.
Chris: Oh, I love it.
Dave: Just try and make them juicy, right? You can do a transition, active scale 1.2, or something like that. You set the scale, like transform scale 1.2, transition scale 0.2 seconds, or something like that. You know, just for a--
Chris: Yeah. Yeah.
Dave: I love that. The place where I use animations is when I want it to do something when it shows up on the page or I toggle a class or something.
Chris: Yeah! That one. Isn't it weird that we have to reach for a keyframe just for that?
Dave: It is because it's a little bit like, I'd rather some on show property because I'm usually going from a zero or to a zero - or something. You know? Usually, yeah, you're trying to -- I want to transition to this state, but the only way to do that is to animate from nothing. You do the modal and you want to fly up just a bit, float up and become opacity one.
Dave: You just want it to--
Chris: All that slide in, slide out, all that type of spirit is all keyframe based.
Chris: It's like when you show up in the DOM, please do this animation, and there is no CSS transition that can do that.
Chris: Well, I guess there kind of is. What you'd have to do is put it in the DOM. Then do a really quick set timeout to add a class, and the class would do this timeout. But that's so kludgy that I'd rather (if I'm just handling it in CSS) do it with a keyframe, with kind of a forwards end state.
Dave: Mm-hmm. Mm-hmm.
Dave: You know it's funny, too. Nuxt has transitions. Sarah Drasner has written about transitions stuff or animating from view-to-view. It's definitely an animation from view-to-view, but in Nuxt it's called a transition. So, anyway.
Chris: Oh, it's like the opposite.
Dave: [Laughter] It's the opposite, but even though you're animating this whole circus of elements going in and out.
Dave: But it's cool.
Chris: That's cool, but it assumes it's kind of a single-page app type of atmosphere, right? It's already on the page and needs to go somewhere else already on the page, which in my mind always is flip territory, right?
Dave: Right. Yeah.
Chris: Position it where it's going to be and then use transforms to put it where it currently is and then un-transform it. Such a clever idea, but it makes everything all juicy. [Laughter]
Dave: Makes it juicy.
Chris: Smooth juice, though.
Dave: Smooth juice.
Chris: No pulp. [Laughter]
Dave: Because you have evaluated the end already, the end state. Yeah.
Dave: That's the trick with all this stuff. Responsive messes it all up, too, because you don't know the height of something. If we just knew the height of things, we'd be super awesome at animating everything. But we just never know the height because the text could grow or somebody could--
Chris: I know. Why?!
Chris: At the height it currently is. Then you can animate it because it has a height on it now that you just measured.
Chris: It's just an additional line.
Chris: That seems like CSS could help us out there.
Chris: It's not like we're asking so much here. Animations to and from auto seem plausible.
Dave: I hope we get that. I know it's complex, but it's also -- I just feel like there's a way to do it, like a pass, like a layout pass that just reports data or something. I don't know.
Chris: Yeah, perhaps.
Dave: For a component or something. I don't know. Maybe.
Chris: I just don't even want to think about it. I just want to be able to say, "Oh, transition height to zero," even though it doesn't have one now, and it just works. That's what I would imagine would work. Maybe it's something like container queries where we're like, "Oh, well, if you want that to work, it has to have contain style on it or something." Okay, fine.
Dave: That would be great. Let's do it.
Chris: Let's do it. You know what got me just yesterday? I wanted to animate some tables, so imagine this is kind of a classic. It's one of these animations where you're not adding it for juiciness. I'm not trying to sell extra copies of my video game because of how amazing it feels. I have a very boring table that's just like top to bottom, you know, row-row-row-row-row-row-row-row-row-row. But there are action buttons on them.
Chris: And they do things. And one of the things is kick that thing off the list. When you do that, if you don't have any animation at all, it just instantly disappears. It can be a little like, you know, you blink and you're like, "Whoa, that was weird. Did it work? Did it not work?" You know? I feel like it's a big improvement to UX if there's a little bit of action there. [Laughter]
In the past, we'd go Ajax to the URL /item/delete and then, on the callback, you'd go l.slideup (or whatever) [laughter] in your jQuery.
Chris: As soon as it's gone from the DOM, there's no way to animate it.
Dave: It's un-animatable. Yeah. Yeah.
Chris: Yeah, so you need to do a little extra hooptie-doopties to get that working. We did it and it was fine, but then it's one thing to just animate the opacity to zero or animate the translate X to 1,000 pixels or something so it looks like this table row is swooshing off the side of it. But in a table, I think the most satisfying animation is something like a slide up where the table row looks like it's collapsing because the point of that is that the rest of the table rows slide up into place.
Dave: Mm-hmm. Mm-hmm.
Chris: That feels good because you mentally understand, like that one is going away and this new one -- like, maybe your mouse cursor is now hovering over a button again, but it's a different button. It's not the same one you were just hovering over.
Chris: That kind of important stuff. Guess what you can't animate on the height on, even if you set a height. A table - anything.
Dave: Oh, really?
Chris: Tables just don't accept height changes. You could take a TR and say height zero and it's going to be like, "No!" [Laughter]
Dave: It just doesn't do it?
Chris: It will ignore you. No.
Chris: Yeah, that's not a thing that you can touch.
Dave: Tables are a cop. Gees!
Chris: Yeah, I know. Super narks on their stuff.
Dave: Dude. Wow.
Chris: The trick is, do you temporarily force it to be display block or something? But then do you write a bunch of CSS to make sure that the layout is exactly the same whether it's a block or a row? If that's the case, why didn't you just do that to begin with? The whole thing is display block. Then it's like, why did you use a table at all? You're just smashing the table-ness out of it. I don't know what to do there.
There is some trickery. Uses scale acts animation and then use additional scale on every single table row after it to pull it up? [Laughter] You know?
Dave: Mm-hmm. Mm-hmm.
Chris: But you often don't have access. You kind of want to isolate animation type of stuff to the thing that you're animating.
Chris: And let everything else flow along with it. I don't think there was a great answer for it. I ended up display blocking the damn thing and not using the tables.
Dave: Just.... Yeah.
Chris: It was an admin tool, so my desire for perfect semantics was lower.
Dave: Yeah, that's where the admin tool vibes.
Dave: I had a situation. Is this fun to talk about these? Let's talk about them.
Dave: I was doing a thing. It's a horizontal scroller of little cardies. You know? I was using scroll snap points. Awesome, right?
Chris: Yeah. I agree.
Dave: Like, this is awesome because you just slide it a bit and it goes, flap, like snaps into the point. This was honestly the first time I've successfully done scroll snap points. I've tried them so many times and just had a bad time. Finally, I was like, "Hey, I think I got it!" because you have to put scroll snap--
Chris: X mandatory.
Dave: X mandatory on the parent and then you scroll snap area (or something) start on or point on the child. Right?
Chris: Children, yeah.
Chris: It's a parent/child party.
Dave: It's a parent/child party, and so I finally got that going. Then the request came in. It would be cool to fast-forward the list to your next uncompleted item, or whatever. Think of YouTube videos or something like that. You want to scroll the horizontal list to the next thing.
I was like, "Yeah, dude. Cool. Easy. Let's do it." Coded up a scroller, and then the problem I had was with the component architecture. It's sort of similar to this display-none animation thing. It was like, "Oh, I can't animate to it because it doesn't exist." [Laughter] It doesn't exist yet in the DOM. You know? Because it's like a JS component, it has to go fetch the data and then populate the data or render the data. Then it can begin to do the scroll operations. I had to use the next tick function in Vue or Nuxt specifically, but that was interesting, too.
Sometimes it's not even display none and show animations are tough, but even display -- like the thing isn't there yet, and so you have to wait, do a request animation frame thing to then go do the thing. That stuff is hard. You don't understand that stuff until you're in it and in the code.
Chris: Yes! That's what I want out of technical articles, by the way. Lately, I've just been saying no to 75% of everything that comes in because it's like, "Can I really do a really super high-level thing on the basics of this thing?" I'm like, no.
Chris: Sometimes, that's interesting. But sometimes, it's just better served by documentation where that's the thing. What I want to know is, did you do it? Were you, Dave Rupert, on some cards with scroll snap points with some deep in the weeds stuff happening? Tell me about that.
Chris: You know? Because then you're covering what it does. It's showing off the feature, but it's also showing reality, the rough edges, and the lived experience of what it's like to do with the tool. That's what technical writing should be.
Dave: I had another one of those. You know those progress meters that go in a circle? You know? I've written a blog post on these arc progress meters before. Then one of the key framers was like, "Oh, there's an easier way to do this," because stroke-array can be zero or one, and it'll just figure out how far it needs to go. You don't have to measure the whole path length and stuff like that if it's going in a full circle.
Chris: Yeah. Right.
Dave: It was like, "Oh, damn. That saves me so much code!" So, I did it in a circle. Then the next client is like, "Oh, we want it in an arc," you know?
Dave: I was like, "Oh, oh, hold on. Hold on. I can just use this code." Then I did it and it was like, "Ooh, it doesn't work," or it mostly works. I had to chuck the stroke-array to 0.875 or something like that, but whatever. I got it working. The arc was correct and I rotated it a bit. But if you do negative numbers (or something like that) or you just say zero of eight complete, it actually goes backward because zero is a value, and so it tries to fill in the arc area that I was trying to eliminate. It was a weird situation.
The chart is great but, until you have a value of zero, and so I just did a display none on the whole thing if the value is zero - but whatever - or the whole arc, so I cheated it, but that was what was in the design comp, so we're fine. But there were a couple other ways I could have cheated it, but it was just kind of like, "Oh, man. That's a bummer." I was hoping it would just be fine. I couldn't render zero in this weird trick, so I couldn't represent zero without just nothing, so there you go.
Chris: Yeah. I think there's some hidden irony to the idea that the people that come across most of these interesting quirks, bugs, and whatever have the most deep experience in the tech are also the people that are so busy doing that kind of work that they don't have time to prioritize writing about it.
Chris: If you're really prioritizing writing, you're doing less work and you have less deep knowledge on the tech. It's not 100%, but there's some baked-in kind of sucky irony about that.
Dave: Oh, yeah. No, I'm definitely -- I'm feeling that. Even my personal life. There are 20 blog posts I want to write, but I've written zero, basically. I'm just too busy. In this stage of my life, I'm just too busy to write a blog post.
Dave: That sucks, but you know it's just what it is. I'm coping at night. I watch anime. You know? [Laughter] I've started watching anime.
Dave: That's what I do, so there you go.
Chris: Well, if that has some positive vibe on your thing. People's incentives are different. You and me, the incentive for blogging couldn't be further apart. For me, I make career-level cash off maintaining this blog, you know.
Dave: Yeah. For me, I get a few thousand hits.
Chris: The satisfaction, though.
Dave: I just get an idea out of my brain. That's quite literally the goal, [laughter] the end state for me. It has plusses and minuses because sometimes I put all this effort into a thought (or whatever) and then it's just like crickets. But you know, whatever.
Chris: Yeah. That happens.
Chris: We've got a question here from one Dough Rah, who writes about the topic of dark mode in email, you know like HTML email. "Is it really okay that email clients are manipulating authored content?" His company has tackled the art of dealing with email in dark mode. "Needless to say, that when dealing with email, development is a huge headache. With email still not up to modern standards, adding dark mode support is indeed a monkey wrench. Calling it support is a major stretch. I wouldn't consider adding a bunch of specific lines for vendor-specific hacks is the right kind of support."
Anyway, I think he's not pleased with all this and goes on, but the point is that, whether you like it or not, when you send an email and the client itself (like on your Android phone, iPhone, or whatever) happens to (at the OS level) have dark mode turned on, your client (like G Mail, Outlook, or whatever is on your phone) might jack dark mode onto your email.
Chris: I've seen it. It happens to the CodePen emails. My phone is in dark mode. I open a transactional email from CodePen; it's dark. It's dark background with light text.
Dave: Whoa! Okay.
Chris: It just jacks into the CSS or whatever and forces that to happen, like the email client is saying, "I'm going to respect the OS level and do some color flopping." It's different, like, the browsers don't do that yet, I don't think. Right? You have to write CSS that will honor the OS-level setting. It will not just force a website into dark mode yet in browsers.
Chris: I don't think.
Dave: Hopefully. Yeah, yeah.
Chris: You can write. I think there's kind of some algorithmic stuff that happens, too, like if there is some kind of -- you know Doug writes in this that it can turn some bright orange into a mustardy yellow just because it decided to because that was a background or a border color or something.
Dave: Color corrected it, yeah, okay.
Chris: Like it's for accessibility, presumably. It's trying to make sure that your colors are discernible still, probably. Not honoring what it looks like but just that it works. I've seen that, too. I've seen in our CodePen emails there's some pretty gnarly colors sometimes. For example, we have some random-ish colors in our CodePen challenges emails that go out every Monday.
Chris: That are like, you know, specific to the sponsor, for example, for the challenges that, in dark mode, just look super weird. So far, I've just let it go. I've just been like, "Whatever. You do you, email client." At least it's usable.
But occasionally, it starts to cross the boundary of, like, that actually looks horrible or is impacting the usability. It's definitely on my rainy day list to rein that in.
Chris: I think if I wrote some media queries to specifically support dark mode that it would allow those. That maybe its algorithms wouldn't kick in, and it would just do what it says to do in the CSS of my email, not its own thing. I don't know that to be true. I haven't really tried it yet. Doug seems to indicate that maybe it's a bit more complicated than that.
What do we think about the overall question? Is it okay that email clients are doing this?
Dave: So... Yeah, I think it is. I mean it's sort of like users over authors. You know?
Chris: Yeah, I get that. It can be an accessibility and power usage thing, too, right?
Dave: I'm a user. I wanted dark mode on here, so I'm going to use dark mode. So, I sort of expect my email client to adapt and figure it out. You know?
Dave: Yeah. It's interesting. Yeah, I just switched to dark mode on my Mac and checked Apple Mail. Some messages do, like the Dropbox Paper one switches to dark. It looks a little weird because the logo is an SVG with a black logo, like black text.
Chris: Oh, so it's just gone?
Chris: It didn't know how to inverse the SVG?
Dave: Yeah, so it just kind of made it disappear. Oh, now I clicked on it again and it's white. It must have heard me talking.
Chris: Oh, my gosh.
Dave: Your computers are listening to you! I don't care what ... says. Yeah, okay, well, that was weird because it just did both. But yeah, it's maybe an issue. Yeah, I think we're just in a weird state. If it's bad, then enough people complain about it, it'll just go away in the app. They're going to be like, "You know we're going to not try to figure this out. Maybe we'll only do it for text emails."
It may be a situation where, as an email writing company, sending company, you need to dial back the styling that you're doing. Maybe you need to think about how does this look if it inverts entirely. That's something--
Chris: Yeah, that's kind of a good point. Rather than trying to really fancy stuff and being mad when it doesn't look in dark mode, just be less fancy.
Dave: Yeah. You might have to tell somebody no, [laughter], you know, at your company, which is a bummer.
Dave: There is this other thing. I'm going to go kind of wild. Jim Nielsen over on the Jim Nielsen blog, he wrote a post about CSS system colors. Are you familiar with these?
Chris: This is such an interesting post. I've been meaning to get a linked post up about it, but I want to learn about it more before I do because it's so interesting. It's like colors like Rebecca purple or light red. Was that one of them? I don't even know. But they're named, right? They're like canvas color.
Chris: You're like, "Whoa! What is that?"
Dave: Canvas would be like your body color, and canvas text would be the color on the text, so white and black or, in dark mode, black and white. Right?
Dave: Link text is blue. Visited text is purple. Active text is red. Button face is gray. Button text is black.
Chris: But, notably, do they change with dark mode?
Dave: They do, so that's kind of like--
Chris: They do.
Dave: They change with dark mode, and it's maybe a way -- it's sort of like UI system fonts. These are system colors.
Dave: You have access to five global variables. [Laughter] No, let's see. [Counting] Eight, ten global variables for colors that exist on the system. I'm not saying this is foolproof or it's going to work or the email clients are good. But this may be an approach you want to do. We can do dark mode emails, but we're kind of limited to these colors because that's what we can guarantee updates and changes.
Chris: Yeah or just write some CSS and fricken' make your own colors. You know?
Dave: Yeah, well--
Chris: I like the idea that this is like system fonts. Use those and they're going to look really native.
Chris: Use these and you have to write less code because they'll just work properly in light mode and dark mode.
Dave: Yeah, and so it's just -- I had never considered this. This is really kind of interesting to me. I think the issue with emails, in general, though, is the inline styles, or historically have been. Maybe it's kind of moving a bit farther out from that. But you can't do a media query, like a dark prefers dark mode media query, in there.
Chris: Inline styles? No, you can't.
Dave: You have to use CSS variables, and so now what number of browsers support CSS variables? Maybe you can sneak one at the top of the document, like switch all the variables at the top of the document or the email. That's hard. I'm going to just say it probably doesn't work.
Chris: That's true. That is the clean way to do it, but you can use a dark mode media query and not custom properties.
Dave: Yeah. Yeah. I think if you wanted to respond to colors in inline style, that's maybe how you'd have to do it.
Chris: Oh, I see.
Dave: But I'm just going to say maybe this is the way to go. [Laughter] Maybe these system colors are kind of your jetpack to get out of all of your problems.
Chris: I wonder, though. Is there quirks with them, too? Has anybody really dug super deep into this? For example, visited text is purple, that classic purple look on the Web when you click a link that you've already seen. Does that mean that you could say, "Div background visited text," and you'll get a purple background? I think it does insinuate that, but really super for sure? Is there nothing? There's no caveats to using that purple? Hmm... I just have a feeling there are some traps here waiting to be found. But I get it. I like it. And it's interesting that it's such a fundamental baked-in part of CSS that I have never heard about until Jim's blog post.
Dave: Yeah. I winced my eyes. I rubbed my eyes in disbelief. I was like, this really is just sitting in there in the spec?
Dave: Yeah, I was just like, I feel gaslit or something because I've never heard of this but it apparently just is sitting there, just living.
Dave: I don't know.
Chris: I'm in a CodePen right now just going body background visited text, and it's a big as purple background. I can go color button face. [Laughter]
Dave: Button face. [Laughter]
Chris: I feel like I'm being rude to the document somehow.
Dave: Yo, hey, button face. [Laughter] "Stop calling me that. Come on!"
Dave: [Laughter] Yeah. No, I mean, but it explains. I don't know. It explains how these things became purple.
Chris: Are there system sizes? Now that we know that we have system fonts and system colors, what other system things do we have?
Chris: Is there system large for named sizes or something?
Dave: Yeah, I don't--
Chris: I don't know.
Dave: What other? Yeah, what other -- size -- what other hidden variables are we sitting on? That's what I want to know. This is a conspiracy. We're unraveling the conspiracy of color module level-four, so please explain this.
Chris: Oh, that's true. This isn't new, though. I had the feeling this is old.
Dave: I think this is all ancient text. Yeah.
Dave: This is ancient stuff, but you know.
Chris: The best example is--
Chris: Oh, transparent. We've had that forever.
Dave: Yeah. Current color. You know, that's like a variable in there.
Chris: Classic. Yeah.
Dave: Just floating around.
Chris: I always liked that for anchor links, too. Jim has a good example of a drop-down menu. That you're actually positioning and coding from scratch, so you very likely have to put a strongly opaque background on it. That's a great use case for canvas coloring. You probably want it to match the background. It's just overlapped, so it has to be a solid color. Using canvas color there probably feels very satisfying. Love it. Then there's probably links in the dropdown, and those could inherit or use current color. Very fancy.
Dave: What's interesting, it's sort of like system fonts. It's like, "Well, I'm just giving up on font control, [laughter] type control. This is going to be Roboto on Android, and it's going to be San Francisco on Apple." Whatever. Hopefully, it looks great. Right?
Then this is sort of doing that with colors. I think he's showing Safari's system or canvas color is 1E1E1E, and Chrome's is 121212, or maybe it's canvas text or something for the dark variant. Yeah. No, that would be the canvas, but anyway. That's an interesting one there, too, because you just kind of have to let colors and type kind of do their thing. Yeah.
Dave: Different worlds.
Chris: I'm looking for system widths. [Laughter]
Dave: Yeah. [Laughter]
Chris: Is there width equals -- I don't know -- half browser. Probably not. There is width fit content.
Dave: Links to Tom Steiner's Web.dev/color-scheme article, this is kind of a Chrome thing, but Thomas is saying, like, take a look at WebKit's UA style sheet. There is one, just a link to the--
Dave: Track.webkit. There's just a lot of junk in here. [Laughter] I don't know. There are QEM units, QEM units.
Chris: Oh, but they're all /apple/ thing?
Dave: Yeah, there's a bunch of stuff in here. This is really interesting what they provide.
Chris: Oh, my gosh.
Dave: They're using a lot of "is" selectors in their default style sheet, which must be kind of new. A lot of WebKits. Yeah.
Chris: Yeah, there is so much. It's like mostly proprietary.
Dave: This could be a talk if somebody wants to give a talk. Just walk us through default style sheets. [Laughter] That would be interesting. And there are "if" statements, so it's obviously some kind of pre-process document, too. So, that's funny.
System UI, Apple system blue. WebKit control background. Yeah, Apple system gets rowdy, so. Hey!
Chris: God, this is fascinating.
Dave: We're learning.
Chris: Okay. Okay.
Dave: Yeah. Yeah, this was -- sorry. Yeah. Where are we? It's 2022. [Laughter] That article was just -- that one was just a shocker because I didn't know it existed and I've been working on the damn websites for 25 years - or whatever. That one was a shocker, so yeah.
Hey, we've got another question. You got time for one more or you've got a hard stop?
Chris: Yeah, let's do it.
Dave: Patrick Bower writes in. "Hi. [Wavy hand]. Thanks for making a great podcast. I work as a UX engineer, which I love, here in London. I have a background both as a designer, but I don't hear much about coded prototypes (a core part of my job) from the engineering community. It would be great to hear about any lean ways of working, tooling, or thoughts in this space for working fast and furious to test ideas and find new solutions. Thanks."
Chris: It just feels like you're Dave, right? You're all about coded prototypes, aren't you?
Dave: Yeah. This is 100% my thing. Please, come to my website. I have a bunch of blog posts I'd love to actually publish about this.
Yeah, prototypes are a big deal. I think people need to do this more often as part of their culture, just like, hey, you had an idea for a feature. I pitched a prototype to a client the other day. They were like, "Hey, we want to do a native app, but we're wondering if a Web app like Ionic or something kind of built on Ionic or Capacitor would kind of fit." You know?
Chris: Oh, I've never heard of them.
Dave: It's like Ionic's phone gap kind of, like how they access native APIs - sort of.
Dave: You know?
Chris: Yeah. Okay.
Dave: So like if you want the camera, you get the camera from Android, or whatever. In Android specifically, you go to their--
Chris: Oh, God. It has the world's fanciest landing page.
Dave: Yeah, so it's their -- Android has the thing. Intense is what it's called. You can have multiple cameras and then choose, like, whenever I'm using a camera, please use this camera app. It's weird, but that's how Android works. They do it on a lot of different levels. Anyway, that Capacitor, I think, negotiates that kind of stuff.
But this client was kind of worried about the juiciness of the animations. This might be a blog post, but I just was like, "Here's the area where native apps are better than websites." It's usually around animations, right? Page transitions, going from one page to another, like the slide drill down, scroll performance on a big giant list, that's getting better. Even just rendering and scroll performance is getting better. But it's still kind of always better in native because they just have more tools around it.
Then when you click a video and it zips to full screen, that's a kludgy experience on the Web and it's really fluid on native. You know what I mean?
Dave: It's all animation-based. That's what makes native better. But I was like, "We could prototype a few views with Capacitor and with some kind of mobile framework just to vibe out, like, is this good? Is this good enough?"
Dave: If it's not, we can pull the plug after we made three views. We're using the same API. We're just spitting out three views. Does it feel good? If it doesn't, let's eject. We spent one week of our time, not ten months, spinning up a mobile project. I think they heard that and were like, "Yeah. Cool. Let's do that."
But if they were like, "We need the full native vibe," that's cool too, but that brings in, like, "Who is going to work on it?" thing. You need a Swift developer. You need a Kotlin developer. You don't just get native juiciness for free, is kind of what I told them. You know? You don't get that for free. You have to work at it. But we can prototype the Web version, the phone ... to the wrapped, app wrap (or whatever) version, and get pretty far.
Dave: You know a lot of the apps we use on a daily basis are just websites. Slack, Discord, they're just websites.
Dave: [Laughter] You know? So--
Chris: Indeed they are.
Dave: Spotify. Just websites.
Chris: [Laughter] Isn't that interesting? The biggest apps, even a lot of Apple stuff, is just a website.
Dave: VS Code.
Chris: That's why it's like, "Please let us in the app store. I don't want to have to wrap it in weird crap. Just let me let the website be in there."
Dave: Yeah. I think, yeah, that would be a big deal for CodePen, probably. [Laughter] Coding environment, casual coding environment.
Chris: Yeah. We'd have a lot of work to do to make it live up to people's expectations, I think.
Dave: And they take 30% of every sign-up. That would be a bummer.
Chris: [Laughter] I don't know. I might be okay with that.
Dave: You might be okay with that? Some mob paying the mafia for your fricken' users? Ah, well--
Chris: Yeah, I don't know. I've literally never thought about, if I could have a native app today for CodePen and put it in the store, would I be mad at that cut or not? I literally haven't spent any time thinking about it. Part of me would be so excited about just having it available that I'd be cool with it, but then you're like, "But really? Thirty? Thirty percent?" [Laughter]
Dave: Yeah. Yeah. It's exciting.
Dave: Until the numbers come through. I don't know, but anyway. Patrick, there is somebody. I'm going to blow this. One second...
There's a prototyping.news newsletter. I want to figure out who does that. Yeah, that's it. Matthias Ott.
Dave: He has prototyping.news. It's a monthly-ish newsletter with just some interesting ideas around prototyping - at all levels, whether that's InVision or code, but definitely driving home the code side of things.
Then Matthias Ott has -- I wish I knew how to say your name. He's from Germany, so I'm trying to put a tiny bit of accent on it. [Laughter] Anyway, he had a really good post about prototyping the other day on his blog. I'm going to blow it on where it is.
Then that design engineering book, do you remember that?
Chris: Yeah. Natalie?
Dave: That was from Natalie, and I want to say Adekunle wrote a chapter on prototyping.
Dave: It was really good, so people are talking about it. It's just not a huge focus. It's not a practice, and a lot of companies don't want to pay for it. You know what I mean? They don't want to pay for somebody to sit around and do "noncontributing work." But for me, it's like these things save so much money if you can spin something up in a day. Tools like Astro or 11ty that we're talking about, man, if you could spin up a little prototype in Astro in one day -- just like you did, Chris, with the CSS-Tricks ZZ--
Dave: You're cooking with grease. You've prototyped out this thing and now -- I think last week you were saying -- oh, I could like, kind of, build a whole -- I could kind of build a headless WordPress with it. You tried it out and now you're kind of like, "Ooh, that's an interesting feeling." That's what prototypes are for, and it took a day. So, there you go.
Chris: Yeah. just to be not wrong about the book, it's Natalya. Sorry, Natalya. Natalya Shelburne, Adekunle, Kim Williams, and Eddie Lou: all four of them contributed to the book.
Dave: Yeah, is that InVision or Digital Ocean? InVision.
Chris: It is an InVision book and it's called Design Engineering Handbook, which is probably good because "design engineering" in Google brings up a bunch of totally unrelated stuff.
Chris: It's also free, so that's a good price for that book.
Dave: No, totally, and there is a whole chapter about prototyping, and it's basically my whole ethos, so it's really good. Is it chapter two? It's not called prototyping, but anyway. Hit me up. I'll find it. But the design engineering process.
And this kind of just bridges that design and engineering gap, you know, where design is maybe going to come up with some ideas. They need some rapid feedback on whether it's even possible. That's what this is for. If you work with two designers, like I do, it's very valuable.
Chris: Indeed. All right, well, thanks, Dave.
Dave: Yeah. let's wrap it up. Thank you, listeners, for downloading this in your podcatcher of choice. Be sure to star, heart, favorite it up. Follow us on Twitter, @ShopTalkShow. Join us in the Discord, patreon.com/shoptalkshow. It's fun.
Chris, do you got anything else you'd like to say?
Chris: [Deep inhale] ShopTalkShow.com.