Lea Verou made a Web Component for processing Markdown. Looks like there were a couple of others out there already, but I agree with Lea in that this is a good use case for the light DOM (as opposed to the shadow DOM that is normally quite useful for web components), and that’s what Lea’s does. The output is HTML so I can imagine it’s ideal you can style it on the page like any other type rather than have to deal with that shadow DOM. I still feel like the styling stories for shadow DOM all kinda suck.
The story of how it came to be is funny and highly relatable. You just want to build one simple thing and it turns out you have to do 15 other things and it takes the better part of a week.
Jhey Tompkins is one of the most prolific CodePen creators out there! Find him as @jh3y on CodePen and @jh3yy on Twitter. His creations tend to have a twist of whimsey while being beautifully designed as well as pushing the platform in unique ways. You’ll always be surprised at a Jhey Pen! I talk with him about the creative process, problem-solving, and sharing what you learn.
For companies of all sizes, Notion provides one central and customizable workspace that can be tailored to fit any team and bring all teams together to get more done and move faster. Notion is an all-in-one team collaboration tool that combines note-taking, document sharing, wikis, project management, and much more into one space that’s simple, powerful, and beautifully designed. Find out how Notion may be the missing piece your team needs to grow, get more done, and delight everyone who uses it in the process.
Rachel and Chris dig into the many, many ways in which we use Notion at CodePen. Heads up, Notion has sponsored a couple of episodes of CodePen Radio lately, but not this. It’s just a tool we heavily use and this podcast is all about that sort of thing. Heck, this podcast itself was planned in a calendar database on Notion, which deals with dates, publication status, sponsors, and all sorts of stuff. And it’s probably one of the least involved Notion setups we have. Much more involved is stuff like project planning and our individual structures for our company-public weeknotes.
The big news from Jetpack is that all backups are realtime now. Realtime backups are awesome. Anything that happens on your site, it’s backed up immediately. That makes backups extremely useful as there is no risk you have to miss three-quarters of a day of content, purchase, comments or anything else because all you have is daily backups.
Huh! I did not realize that CSS custom properties had their own resolution behavior for how !important works in their values. Uh, despite writing a guide about them. 😬 But hey it’s now updated.
div {
--color: red !important;
color: var(--color);
color: yellow;
}
It kinda feels like red should win, but because !important is ultimately stripped from the custom property value, yellow wins it out. And it’s not because the color declaration comes last — if color: red !important; was the first declaration, then red would win.
But it’s not like !important is just stripped and ignored; it’s used in a scoped way, affecting which custom property value wins. But then !important is gone when that value is applied. Stefan’s example:
div {
/*
`!important` overrules the
other `--color` definitions
*/
--color: red !important;
color: var(--color);
}
.class {
--color: blue;
}
#id {
--color: yellow;
}
This feels weird (to me) as you’d think yellow declared on #id would win because it has the highest specificity. But that’s the deal with the scoped behavior — !important makes red the winner, then is applied to the color as such.
I was reading Jake’s “Cross-fading any two DOM elements is currently impossible” which is a wonderfully nerdy deep dive into how there is no real way to literally cross-fade elements. Yeah, you can animate both of their opacities, but even that isn’t quite the same. Turns out there is a Chrome/WebKit-only CSS function call called -webkit-cross-fade() that does the trick. MDN says it’s specced, but the implemented version differs, so it’s a bit of a mess… but it does exist:
The first thing I thought of was: if one of the images was just a blank transparent image, wouldn’t that apply partial transparency to the other one? And thus it’s kind of a proxy for background-opacity (which doesn’t exist but feels like it should).
It doesn’t work in Firefox but it does in everything else. Plus, you can test for support right in CSS and do something different if this isn’t just an enhancement.
@supports (background: -webkit-cross-fade(url(), url(), 50%)) {
/* Only apply the idea if supported, do the Firefox fallback outside of this */
}
Today I get the pleasure of talking with Aaron Iker. Aaron builds incredibly delightful bits and bobs of UI that give you the feeling of hey, I bet I could actually use this! And that’s exactly what Aaron wants you to do. He takes care to make sure the code is easy for you to use if you wish. This idea of taking somewhat practical-looking UI elements, like buttons, loaders, toggles, etc, and then making them do something unexpected and fun is a perfect fit for popularity on CodePen. Last year, Aaron occupied 10 spots in the Top 100! Aaron’s advice: keep challenging yourself.
Netlify is Jamstack hosting with all sorts of features to help make developing sites easier (have you seen Netlify Dev? You can run the whole platform locally) and deployed sites better. But Netlify is a big place! They do all sorts of community things like Jamstack Explorers, a whole learning platform for leveling up your Jamstack skills. Not to mention several YouTube channels loaded with learning and fun.
You get an extra-round-y appearance in Safari, which at one time matched the macOS look for search inputs, but not really anymore. I don’t hate the look, except…
Safari totally ignores the font-size you set on it, so careful about that. Unless you smash off the round-y look with -webkit-appearance: none—then you can, so probably 92% of all websites do this.
You get a little × icon inside the input (when it has a value) that clears it out. This is probably the best reason to use it, and mercifiully you get to keep it even after resetting the appearance.
You get the satisfaction of knowing that you’re using the semantically correct input type for the job, assuming you are building a thing that actually searches something.
You get past search terms with autocomplete. Browsers store those past search terms and offer a menu for autocompleting them. I’m trying to make this a list of things that are unique to search inputs, and I can prove this happens on non-search inputs. But hey, it does make the most sense on search inputs.
You get the pleasure of adding a role to the parent form (i.e. <form role="search">) because that helps assistive technology announce it as a search form.
You get to remember to add a proper <label> to the input. Just using a magnifying glass icon or just a placeholder alone won’t cut it, even though that’s what a lot of designs call for visually.
You get a super weird incremental attribute that sends a debounced search event to the DOM element itself. I guess that is useful for live search UX. But it’s non-standard and not in Firefox so probably don’t count on it (via Christian Shaefer).
Upon hearing “sticky footer” these days, I would think most people imagine a position: sticky situation where a footer element appears fixed on the screen while in the scrolling context of some parent element.
That’s not quite what I’m talking about here. “Sticky footers” were a UI concept before position: sticky existed and they mean something slightly different. The idea is that they stick to the bottom of the screen, even when the content of the page isn’t enough to push them there. But if there is enough content, they are happily pushed down.
We covered five ways to do this in years past, which included techniques that are somewhat modern, including calc(), flexbox, and CSS Grid.
Enter a sixth challenger! Reader Sílvio Rosa wrote in with this:
(Probably easiest to check out on a medium-sized desktop screen, which is kinda where sticky footers matter the most anyway.)
It’s pretty much just this:
html, body { height: 100%;}
body > footer {
position: sticky;
top: 100vh;
}
What I like about it is that it doesn’t require any special extra wrapper for non-footer content.
It’s also a little brain-bending. When I see top: 100vh; I think well that won’t work because it will push the footer outside the viewable area. But that’s the clever bit. It will do that no matter how big the footer is (no magic numbers), and then the sticky positioning will “suck it back up” to stick along the bottom edge. But it will never overlap content, so it’s happy to be pushed down below content, which is a core tenant of the sticky footer pattern.
Remember when Ahmad Shadeed wrote about that border-radius “toggle” he found in Facebook’s CSS? It was interesting! I covered it. A few weeks after that surge of linkage, a couple of articles came out digging into it a little deeper.
While undoubtedly clever, and super interesting to read about, I side with Robin Rendle in the CSS-Tricks newsletter when he says:
I can’t help but feel that it’s a little too smart.
I have to agree here. Tricks like this have their place, and Facebook (which can clearly afford to hire the best of the best CSS developers) might be one of them. But speaking personally, when forced to pick between a trick like this and an ever-so-slightly less optimal but far more readable solution (say, a media query), in 99% of cases I’d plump for the latter.
Michelle is aware that a media query isn’t the same solution here. A non-clever solution would be a container query. I agree as well. I almost never opt for tricky solutions in production, as even if they seem to work, I worry about the long term maintenance and sometimes even the fragility of the solution.
Stefan Judis looked at how we might pull of the same “conditional border-radius” idea only using the upcoming container queries syntax.
/* If the container's width is equal to or greater than
the viewport width, remove the border-radius */
@container (width >= 100vw) {
.conditional-border-radius {
border-radius: 0;
}
}
That’s pretty darn clear to me. Stefan also mentions that if we could use the theoretically upcoming @when feature, it could be even clearer:
That is a big maybe, as there is no evidence these brand new specs will overlap like this. I hope they do though. CSS has gotten much more logical and readable over the years and this would keep that train moving.
The 9999 multiplication means that you’ll never get low-positive numbers. It’s a toggle. You’ll either get 8px or 0px and nothing in between. Try removing that part, resizing the screen, and seeing it sorta morph as the viewport becomes close to the component size
But I regretted not putting a video in there to make the concept clearer, so I’ll rectify that here.
Scott digs into the history of the <menu> element. He traced it as far back as HTML 2 (!) in a 1994 changelog. The vibe then, it seems, was to mark up a list. I would suspect the intention is much like <nav> is today, but I really don’t know.
Short story: HTML 4 deprecated it, HTML 5 revived it—this time as a “group of commands”—and then HTML 5.2 deprecated it again. Kind of a bummer since it has some clear use cases.
So, it’s been quite the roller coaster for ol’ <menu>! There never seems to be any easy wins for HTML evolution. As of now, it’s in “don’t bother” territory:
I really wrote this post as a sort of counter point to the often uttered phrase “use semantic HTML and you get accessibility for free!” That statement, on its surface, is largely true. And you should use semantic HTML wherever its use is appropriate. <menu>, unfortunately, doesn’t really give us all that much, even though it has clearly defined semantics. Its intended semantics and what we actually need in reality are better served by either just using the more robust <ul> element, or creating your own role=toolbar, menubar, etc.. Using this semantic element, for semantics sake, is just that.
Marie and Chris talk about CodePen Challenges, which have been going strong for many years now. The gist is that you pop in and make something along a theme. The “challenge” is doing the work (they aren’t meant to be tricky otherwise). We’ve seen people seriously level up their skills by participating, but of course, there is no obligation, and no prizes other than the satisfaction of a job well done.
One interesting twist is that Chris used to do a lot of the challenges while Marie was running the podcast, but we just up and switched jobs and we both prefer our new jobs much better (for now!).
Just look at the October 2021 changelog at Netlify. They are always building things and making the features they offer better. We know firsthand how difficult that is to pull off, so hats off! One feature (BETA) that is definitely worth a look is On-Demand Builders. What a great idea for making your builds and deploys fast and efficient.
Bonafide CSS trick alert! Nelson Menezes figured out a new way (that only works in Firefox for now) that is awfully clever.
Perhaps you know that CSS cannot animate to auto dimensions, which is super unfortunate. Animating from zero to “whatever is necessary” would be very helpful very often. We’ve documented the available techniques. They boil down to:
Animate the max-height to some more than you need value, which makes timing easing imprecise and janky.
Use JavaScript to measure the final size and animate to that, which means… using JavaScript.
Nelson’s technique is neither of those, nor some transform-based way with visual awkwardness. This technique uses CSS Grid at its core…
Unbelievably, in Firefox, that transitions content inside that area between 0 and the natural height of the content. There is only a little more to it, like hiding overflow and visibility to make it look right while maintaining accessibility:
That’s wonderful. Let’s get some stars on this issue and maybe Chrome will pick it up. But of course, even better would be if auto height transitions just started working. I can’t imagine that’s totally outside the realm of possibility.
Container queries are going to solve this long-standing issue in web design where we want to make design choices based on the size of an element (the container) rather than the size of the entire page. So, if a container is 600px wide, perhaps it has a row-like design, but any narrower than that it has a column-like design, and we’ll have that kind of control. That’s much different than transitioning between layouts based on screen size.
We can already size some things based on the size of an element, thanks to the % unit. For example, all these containers are 50% as wide as their parent container.
The % here is 1-to-1 with the property in use, so width is a % of width. Likewise, I could use % for font-size, but it will be a % of the parent container’s font-size. There is nothing that lets me cross properties and set the font-size as a % of a container’s width.
That is, unless we get container units! Here’s the table of units per the draft spec:
unit
relative to
qw
1% of a query container’s width
qh
1% of a query container’s height
qi
1% of a query container’s inline size
qb
1% of a query container’s block size
qmin
The smaller value of qi or qb
qmax
The larger value of qi or qb
With these, I could easily set the font-size to a percentage of the parent container’s width. Or line-height! Or gap! Or margin! Or whatever!
Miriam notes that we can actually play with these units right now in Chrome Canary, as long as the container queries flag is on.
I had a quick play too. I’ll just put a video here as that’ll be easier to see in these super early days.
And some great exploratory work from Scott here as well:
Ahmad Shadeed is also all over this!
Query units can save us effort and time when dealing with things like font-size, padding, and margin within a component. Instead of manually increasing the font size, we can use query units instead.
Here’s Atif Afzal on using a <div> that is permanently on the page where tooltips are added/removed and how they perform vastly better than plopping those same tooltips right into the <body>. It’s not really discussed, but the reason you put them that high-up in the DOM is so you can absolutely position them exactly where you need to on the page without having to deal with hidden overflow or relative parents and the like.
To my amazement, just having a separate container without even adding the [CSS] contain property fixed the performance. The main problem now, was to explain it. First I thought this might be some internal browser heuristic optimizing the Recalculate Style, but there is no black magic and I discovered the reason.
The trick is to avoid forced recalculations of style:
[…] The tooltip container is not visible in the page, so modifying it doesn’t invalidate the complete page render tree. If the tooltip container would have been visible in the page, then the complete render tree would be invalidated but in this case only an independent subtree was invalidated. Recalculating Style for a small subtree of 3 doesn’t take a lot of time and hence is faster.
Looks like popper.js was used here, so you have to be smart about it. We use toast messages on CodePen, and it’s the only third-party component we use at the moment: react-hot-toast. I checked it, and not only do we tuck the messages in a <div> of our own, but the library itself does that, so I think we’re in the clear.
In the olden days (like, a few weeks ago), the Pinned Items UI was much less capable. You could certainly pin things, and open up a menu to see a list of what you pinned, but there wasn’t any context. There was no visual preview to quickly identify them. There was no metadata like when it was created or updated.
We’ve updated the UI so now you’re Pinned Items always open up in a modal (it’s the same everywhere now) and you can flip between grid view:
And list view:
We’re hoping this will make it much more convenient to get to items you want to really quickly get back to from no matter where you are on CodePen.
Zach did that thing where each of his blog posts has a special URL with the design of social image card that is screenshat by a headless browser (like Puppeteer) and used as a true meta Open Graph image, meaning it’s displayed on Twitter, Facebook, iMessage, Slack, Discord, and whatever else supports that card look.
I like it. Even though I’ve got a pretty good solution cooking now (for WordPress), the templates aren’t controlled with HTML/CSS like I wish they were.
As bit of yang to the ying here, Jim has some thoughts on the not-so-great Aspects of Open Graph images:
I feel like they’ve been hijacked by auto-generated computer imagery serving as attention-grabbing filler more than supportive expression.
It’s kinda like… we can add Open Graph images, and we essentially get a totally free massive clickable target for hungry fingers, so we do add Open Graph images — even when that image is, well, boring. Just auto-generated computer barf of title text with branding. Jim’s post has examples.
I get where Jim is coming from, and I suppose I’m guilty to some degree. I feel like we’re a cut-above on CSS-Tricks though, if you’ll pardon a taste of defensiveness, because:
We have a variety of templates to choose from to switch it up, like a quote design.
We incorporate custom imagery into the final card, meaning most cards are somewhat visually unique.
We don’t just brand the cards, we usually incorporate the author for a little extra high five for the person, rather than just our brand.
Reflecting back on this time, I think there are a few key concepts that were vital to things finally all making sense and fitting together. These were:
• The Box Model (e.g. box-sizing, height, width, margin, padding) • Layout (e.g. display) • Document Flow and Positioning (e.g. position, top, left, etc.)
The perfect cross-platform serif and sans-serif font stacks — Daniel Aleksandersen has lots of details about pre-installed fonts across operating systems, like: Mac and iOS also come with Helvetica Neue preinstalled. It addresses some of Helvetica’s legibility issues … On Windows, you might find a more modern version of Arial called Arial Nova. Arial Nova makes much the same legibility improvements and compromises as Helvetica Neue.
Pairing fonts – 3 ways to find great typeface combinations — Oliver Schöndorfer says it’s an artistist decision so don’t be afraid to try stuff. But also, do you even need more than one? If so, have a reason. Repeat your font choices as often as you can, and only when something does not work in a given situation, add a new style.
Twitter thread about Really Sans — Riley Cran gets into optical sizing and how Really Sans[…] is a sans serif typeface with two optical sizes. The small optical size works for text. The large optical size revives the tone of the 1970s headlines. I see Riley is using the pricing model based on # of employees rather than pageviews which I love.
Helvetica® Now Variable — I think having major fonts like Helvetica, that a lot of brands rely on, is the kind of thing that pushes the needle on variable fonts forward.
Fonts in the Twilight Zone — John Boardley looks at some rather unclassifiable fonts: Among my favorite kinds of typefaces are those that don’t fit neatly into predefined or existing categories; those that dip their toes into more than one genre, or take their cues from disparate historical periods.
Coding with Character — Doug Wilson looks at coding typefaces: If you spend all day looking at code, letters, and characters—why not make it fun?I’m down.