Front End Web Development
Two CSS Properties for Trimming Text Box Whitespace
The text-box-trim and text-box-edge properties in CSS enable developers to trim specifiable amounts of the whitespace that appear above the first formatted line of text and below the last formatted line of text in a text box, making the text box vertically larger than the content within.
This whitespace is called leading, and it appears above and below (so it’s two half-leadings, actually) all lines of text to make the text more readable. However, we only want it to appear in between lines of text, right? We don’t want it to appear along the over or under edges of our text boxes, because then it interferes with our margins, paddings, gaps, and other spacings.
As an example, if we implement a 50px margin but then the leading adds another 37px, we’d end up with a grand total of 87px of space. Then we’d need to adjust the margin to 13px in order to make the space 50px in practice.
As a design systems person, I try to maintain as much consistency as possible and use very little markup whenever possible, which enables me to use the adjacent-sibling combinator (+) to create blanket rules like this:
/* Whenever <element> is followed by <h1> */ <element> + h1 { margin-bottom: 13px; /* instead of margin-bottom: 50px; */ }This approach is still a headache since you still have to do the math (albeit less of it). But with the text-box-trim and text-box-edge properties, 50px as defined by CSS will mean 50px visually:
Disclaimer: text-box-trim and text-box-edge are only accessible via a feature flag in Chrome 128+ and Safari 16.4+, as well as Safari Technology Preview without a feature flag. See Caniuse for the latest browser support.
Start with text-box-trimtext-box-trim is the CSS property that basically activates text box trimming. It doesn’t really have a use beyond that, but it does provide us with the option to trim from just the start, just the end, both the start and end, or none:
text-box-trim: trim-start; text-box-trim: trim-end; text-box-trim: trim-both; text-box-trim: none;Note: In older web browsers, you might need to use the older start/end/both values in place of the newer trim-start/trim-end/trim-both values, respectively. In even older web browsers, you might need to use top/bottom/both. There’s no reference for this, unfortunately, so you’ll just have to see what works.
Now, where do you want to trim from?You’re probably wondering what I mean by that. Well, consider that a typographic letter has multiple peaks.
There’s the x-height, which marks the top of the letter “x” and other lowercase characters (not including ascenders or overshoots), the cap height, which marks the top of uppercase characters (again, not including ascenders or overshoots), and the alphabetic baseline, which marks the bottom of most letters (not including descenders or overshoots). Then of course there’s the ascender height and descender height too.
You can trim the whitespace between the x-height, cap height, or ascender height and the “over” edge of the text box (this is where overlines begin), and also the white space between the alphabetic baseline or descender height and the “under” edge (where underlines begin if text-underline-position is set to under).
Don’t trim anythingtext-box-edge: leading means to include all of the leading; simply don’t trim anything. This has the same effect as text-box-trim: none or forgoing text-box-trim and text-box-edge entirely. You could also restrict under-edge trimming with text-box-trim: trim-start or over edge trimming with text-box-trim: trim-end. Yep, there are quite a few ways to not even do this thing at all!
Newer web browsers have deviated from the CSSWG specification working drafts by removing the leading value and replacing it with auto, despite the “Do not ship (yet)” warning (*shrug*).
Naturally, text-box-edge accepts two values (an instruction regarding the over edge, then an instruction regarding the under edge). However, auto must be used solo.
text-box-edge: auto; /* Works */ text-box-edge: ex auto; /* Doesn't work */ text-box-edge: auto alphabetic; /* Doesn't work */I could explain all the scenarios in which auto would work, but none of them are useful. I think all we want from auto is to be able to set the over or under edge to auto and the other edge to something else, but this is the only thing that it doesn’t do. This is a problem, but we’ll dive into that shortly.
Trim above the ascenders and/or below the descendersThe text value will trim above the ascenders if used as the first value and below the descenders if used as the second value and is also the default value if you fail to declare the second value. (I think you’d want it to be auto, but it won’t be.)
text-box-edge: ex text; /* Valid */ text-box-edge: ex; /* Computed as `text-box-edge: ex text;` */ text-box-edge: text alphabetic; /* Valid */ text-box-edge: text text; /* Valid */ text-box-edge: text; /* Computed as `text-box-edge: text text;` */It’s worth noting that ascender and descender height metrics come from the fonts themselves (or not!), so text can be quite finicky. For example, with the Arial font, the ascender height includes diacritics and the descender height includes descenders, whereas with the Fraunces font, the descender height includes diacritics and I don’t know what the ascender height includes. For this reason, there’s talk about renaming text to from-font.
Trim above the cap height onlyTo trim above the cap height:
text-box-edge: cap; /* Computed as text-box-edge: cap text; */Remember, undeclared values default to text, not auto (as demonstrated above). Therefore, to opt out of trimming the under edge, you’d need to use trim-start instead of trim-both:
text-box-trim: trim-start; /* Not text-box-trim: trim-both; */ text-box-edge: cap; /* Not computed as text-box-edge: cap text; */ Trim above the cap height and below the alphabetic baselineTo trim above the cap height and below the alphabetic baseline:
text-box-trim: trim-both; text-box-edge: cap alphabetic;By the way, the “Cap height to baseline” option of Figma’s “Vertical trim” setting does exactly this. However, its Dev Mode produces CSS code with outdated property names (leading-trim and text-edge) and outdated values (top and bottom).
Trim above the x-height onlyTo trim above the x-height only:
text-box-trim: trim-start; text-box-edge: ex; Trim above the x-height and below the alphabetic baselineTo trim above the x-height and below the alphabetic baseline:
text-box-trim: trim-both; text-box-edge: ex alphabetic; Trim below the alphabetic baseline onlyTo trim below the alphabetic baseline only, the following won’t work (things were going so well for a moment, weren’t they?):
text-box-trim: trim-end; text-box-edge: alphabetic;This is because the first value is always the mandatory over-edge value whereas the second value is an optional under-edge value. This means that alphabetic isn’t a valid over-edge value, even though the inclusion of trim-end suggests that we won’t be providing one. Complaints about verbosity aside, the correct syntax would have you declare any over-edge value even though you’d effectively cancel it out with trim-end:
text-box-trim: trim-end; text-box-edge: [any over edge value] alphabetic; What about ideographic glyphs?It’s difficult to know how web browsers will trim ideographic glyphs until they do, but you can read all about it in the spec. In theory, you’d want to use the ideographic-ink value for trimming and the ideographic value for no trimming, both of which aren’t unsupported yet:
text-box-edge: ideographic; /* No trim */ text-box-edge: ideographic-ink; /* Trim */ text-box-edge: ideographic-ink ideographic; /* Top trim */ text-box-edge: ideographic ideographic-ink; /* Bottom trim */ text-box, the shorthand propertyIf you’re not keen on the verbosity of text box trimming, there’s a shorthand text-box property that makes it somewhat inconsequential. All the same rules apply.
/* Syntax */ text-box: [text-box-trim] [text-box-edge (over)] [text-box-edge (under)]? /* Example */ text-box: trim-both cap alphabetic; Final thoughtsAt first glance, text-box-trim and text-box-edge might not seem all that interesting, but they do make spacing elements a heck of a lot simpler.
Is the current proposal the best way to handle text box trimming though? Personally, I don’t think so. I think text-box-trim-start and text-box-trim-end would make a lot more sense, with text-box-trim being used as the shorthand property and text-box-edge not being used at all, but I’d settle for some simplification and/or consistent practices. What do you think?
There are some other concerns too. For example, should there be an option to include underlines, overlines, hanging punctuation marks, or diacritics? I’m going to say yes, especially if you’re using text-underline-position: under or a particularly thick text-decoration-thickness, as they can make the spacing between elements appear smaller.
Two CSS Properties for Trimming Text Box Whitespace originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
What’s Old is New
I collect a bunch of links in a bookmarks folder. These are things I fully intend to read, and I do — eventually. It’s a good thing bookmarks are digital, otherwise, I’d need a bigger coffee table to separate them from the ever-growing pile of magazines.
The benefit of accumulating links is that the virtual pile starts revealing recurring themes. Two seemingly unrelated posts published a couple months apart may congeal and become more of a dialogue around a common topic.
I spent time pouring through a pile of links I’d accumulated over the past few weeks and noticed a couple of trending topics. No, that’s not me you’re smelling — there’s an aroma of nostalgia in the air., namely a newfound focus on learning web fundamentals and some love for manual deployments.
Web Developers, AI, and Development FundamentalsUltimately, it is not about AI replacing developers, but about developers adapting and evolving with the tools. The ability to learn, understand, and apply the fundamentals is essential because tools will only take you so far without the proper foundation.
ShopTalk 629: The Great Divide, Global Design + Web Components, and Job TitlesChris and Dave sound off on The Great Divide in this episode and the rising value of shifting back towards fundamentals:
Dave: But I think what is maybe missing from that is there was a very big feeling of disenfranchisement from people who are good and awesome at CSS and JavaScript and HTML. But then were being… The market was shifting hard to these all-in JavaScript frameworks. And a lot of people were like, “I don’t… This is not what I signed up for.”
[…]
Dave: Yeah. I’m sure you can be like, “Eat shit. That’s how it is, kid.” But that’s also devaluing somebody’s skillset. And I think what the market is proving now is if you know JavaScript or know HTML, CSS, and regular JavaScript (non-framework JavaScript), you are once again more valuable because you understand how a line of CSS can replace 10,000 lines of JavaScript – or whatever it is.
Chris: Yeah. Maybe it’s coming back just a smidge–
Dave: A smidge.
Chris: –that kind of respecting the fundamental stuff because there’s been churn since then, since five years ago. Now it’s like these exclusively React developers we hired, how useful are they anymore? Were they a little too limited and fundamental people are knowing more? I don’t know. It’s hard to say that the job industry is back when it doesn’t quite feel that way to me.
Dave: Yeah, yeah. Yeah, who knows. I just think the value in knowing CSS and HTML, good HTML, are up more than they maybe were five years ago.
Just a Spec: HTML Finally Gets the Respect It DeservesJared and Ayush riffin’ on the first ever State of HTML survey, why we need it, and whether “State of…” surveys are representative of people who work with HTML.
[…] once you’ve learned about divs and H’s 1 through 6, what else is there to know? Quite a lot, as it turns out. Once again, we drafted Lea Verou to put her in-depth knowledge of the web platform to work and help us craft a survey that ended up reaching far beyond pure HTML to cover accessibility, web components, and much more.
[…]
You know, it’s perfectly fine to be an expert at HTML and CSS and know very little JavaScript. So, yeah, I think it’s important to note that as we talk about the survey, because the survey is a snapshot of just the people who know about the survey and answer the questions, right? It’s not necessarily representative of the broad swath of people around the world who have used HTML at all.
[…]
So yeah, a lot of interest in HTML. I’m talking about HTML. And yeah, in the conclusion, Lea Verou talks about we really do have this big need for more extensibility of HTML.
In a more recent episode:
I’m not surprised. I mean, when someone who’s only ever used React can see what HTML does, I think it’s usually a huge revelation to them.
[…]
It just blows their minds. And it’s kind of like you just don’t know what you’re missing out on up to a point. And there is a better world out there that a lot of folks just don’t know about.
[…]
I remember a while back seeing a post come through on social media somewhere, somebody’s saying, oh, I just tried working with HTML forms, just standard HTML forms the first time and getting it to submit stuff. And wait, it’s that easy?
Yeah, last year when I was mentoring a junior developer with the Railsworld conference website, she had come through Bootcamp and only ever done React, and I was showing her what a web component does, and she’s like, oh, man, this is so cool. Yeah, it’s the web platform.
Reckoning: Part 4 — The Way OutAlex Russell in the last installment of an epic four-part series well worth your time to fully grasp the timeline, impact, and costs of modern JavsaScript frameworks to today’s development practices:
Never, ever hire for JavaScript framework skills. Instead, interview and hire only for fundamentals like web standards, accessibility, modern CSS, semantic HTML, and Web Components. This is doubly important if your system uses a framework.
Semi-Annual Reminder to Learn and Hire for Web StandardsThis is a common cycle. Web developers tire of a particular technology — often considered the HTML killer when released — and come out of it calling for a focus on the native web platform. Then they decide to reinvent it yet again, but poorly.
There are many reasons companies won’t make deep HTML / CSS / ARIA / SVG knowledge core requirements. The simplest is the commoditization of the skills, partly because framework and library developers have looked down on the basics.
The anchor elementHeydon Pickering in a series dedicated to HTML elements, starting alphabetically with the good ol’ anchor <a>:
Sometimes, the <a> is referred to as a hyperlink, or simply a link. But it is not one of these and people who say it is one are technically wrong (the worst kind of wrong).
[…]
Web developers and content editors, the world over, make the mistake of not making text that describes a link actually go inside that link. This is collosally unfortunate, given it’s the main thing to get right when writing hypertext.
AI Myth: It lets me write code I can’t on my ownAt the risk of being old and out-of-touch: if you don’t know how to write some code, you probably shouldn’t use code that Chat GPT et al write for you.
[…]
It’s not bulletproof, but StackOverflow provides opportunities to learn and understand the code in a way that AI-generated code does not.
What Skills Should You Focus on as Junior Web Developer in 2024?Let’s not be old-man-shakes-fist-at-kids.gif about this, but learning the fundamentals of tech is demonstrateably useful. It’s true in basketball, it’s true for the piano, and it’s true in making websites. If you’re aiming at a long career in websites, the fundamentals are what powers it.
[…]
The point of the fundamentals is how long-lasting and transferrable the knowledge is. It will serve you well no matter what other technologies a job might have you using, or when the abstractions over them change, as they are want to do.
As long as we’re talking about learning the fundamentals…
The BasicsOh yeah, and of course there’s this little online course I released this summer for learning HTML and CSS fundamentals that I describe like this:
The Basics is more for your clients who do not know how to update the website they paid you to make. Or the friend who’s learning but still keeps bugging you with questions about the things they’re reading. Or your mom, who still has no idea what it is you do for a living. It’s for those whom the entry points are vanishing. It’s for those who could simply sign up for a Squarespace account but want to understand the code it spits out so they have more control to make a site that uniquely reflects them.
Not all this nostalgia is reserved only for HTML and CSS, but for deploying code, too. A few recent posts riff on what it might look like to ship code with “buildless” or near “buildless” workflows.
Raw-Dogging WebsitesIt is extraordinarily liberating. Yes, there are some ergonomic inefficiencies, but at the end of the day it comes out in the wash. You might have to copy-and-paste some HTML, but in my experience I’d spend that much time or more debugging a broken build or dependency hell.
Going BuildlessMax Böck in a follow-up to Brad:
So, can we all ditch our build tools soon?
Probably not. I’d say for production-grade development, we’re not quite there yet. Performance tradeoffs are a big part of it, but there are lots of other small problems that you’d likely run into pretty soon once you hit a certain level of complexity.
For smaller sites or side projects though, I can imagine going the buildless route – just to see how far I can take it.
Manual ’till it hurtsJeremy Keith in a follow-up to Max:
If you’re thinking that your next project couldn’t possibly be made without a build step, let me tell you about a phrase I first heard in the indie web community: “Manual ‘till it hurts”. It’s basically a two-step process:
- Start doing what you need to do by hand.
- When that becomes unworkable, introduce some kind of automation.
It’s remarkable how often you never reach step two.
I’m not saying premature optimisation is the root of all evil. I’m just saying it’s premature.
That’s it for this pile of links and good gosh my laptop feels lighter for it. Have you read other recent posts that tread similar ground? Share ’em in the comments.
What’s Old is New originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
Steven Heller’s Font of the Month: Rig Solid
Read the book, Typographic Firsts
Steven Heller takes a closer look at Jamie Clarke’s 3D Rig Solid font family.
The post Steven Heller’s Font of the Month: Rig Solid appeared first on I Love Typography.
Quick Hit #18
PSA: Today’s the day that Google’s performance tools officially stops supporting the First Input Delay (FID) metric that was replaced by Interaction to Next Paint (INP).
Quick Hit #18 originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
Sanding UI
Jim hit a snag while working on a form. Placing labels next to inputs is trivial with flexbox, sure, but what happened in Jim’s case was a bit of dead-clicking between the labels and radio buttons.
The issue? Not the markup, that’s all semantic and cool. Turns out the gap he placed between the elements is non-interactive. Makes sense when you think about it, but frustrating nonetheless because it looks like a bug and feels like a bug even though there’s nothing wrong with the styles.
The solution’s easy enough: padding along the inside edge of the input extends its box dimensions, allowing the added space to remain interactive with visual spacing. Margin wouldn’t work since it’s akin to gap in that it pushes the element’s box instead of expanding it.
I’m linking up Jim’s article because it’s a perfect demonstration that CSS is capable of accomplishing the same thing in many ways. It’s easy to fall into the trap of “single-solution” thinking, but CSS doesn’t want anything to do with that. It’ll instead challenge you to adapt toward open-minded strategies, perhaps even defensive ones.
Sanding UI originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
Time Travelling CSS With :target
Checkbox and radio button hacks are the (in)famous trick for creating games using just CSS. But it turns out that other elements based on user input can be hacked and gamified. There are very cool examples of developers getting creative with CSS games based on the :hover pseudo-class, and even other games based on the :valid pseudo-class.
What I’ve found, though, is that the :target pseudo-class seems relatively unexplored territory in this area of CSS hacking. It’s an underrated powerful CSS feature when you think about it: :target allows us to style anything based on the selected jump link, so we have a primitive version of client-side routing built into the browser! Let’s go mad scientist with it and see where that takes us.
Unbeatable AI in CSSDid I type those words together? Are we going to hack CSS so hard that we hit the singularity? Try to beat the stylesheet below at Tic Tac Toe and decide for yourself.
CodePen Embed FallbackThe stylesheet will sometimes allow the game to end in a draw, so you at least have a smidge of hope.
No need to worry! CSS hasn’t gone Skynet on us yet. Like any CSS hack, the rule of thumb to determine whether a game is possible to implement with CSS is the number of possible game states. I learned that when I was able to create a 4×4 Sudoku solver but found a 9×9 version pretty darn near impossible. That’s because CSS hacks come down to hiding and showing game states based on selectors that respond to user input.
Tic Tac Toe has 5,478 legal states reachable if X moves first and there’s a famous algorithm that can calculate the optimal move for any legal state. It stands to reason, then, that we can hack together the Tic Tac Toe game completely in CSS.
OK, but how?In a way, we are not hacking CSS at all, but rather using CSS as the Lord Almighty intended: to hide, show, and animate stuff. The “intelligence” is how the HTML is generated. It’s like a “choose your own adventure” book of every possible state in the Tic Tac Toe multiverse with the empty squares linked to the optimal next move for the computer.
We generate this using a mutant version of the minimax algorithm implemented in Ruby. And did you know that since CodePen supports HAML (which supports Ruby blocks), we can use it secretly as a Ruby playground? Now you do.
Each state our HAML generates looks like this in HTML:
<div class="b" id="--OOX----"> <svg class="o s"> <circle></circle> </svg> <a class="s" href="#OXOOX----"> <div></div> </a> <svg class="o s"> <circle class="c"></circle> </svg> <svg class="o s"> <circle class="c"></circle> </svg> <div class="x"></div> <a class="s" href="#O-OOXX---"> <div></div> </a> <a class="s" href="#O-OOX-X--"> <div></div> </a> <a class="s" href="#O-OOX--X-"> <div></div> </a> <a class="s" href="#O-OOX---X"> <div></div> </a> </div>With a sprinkling of surprisingly straightforward CSS, we will display only the currently selected game state using :target selectors. We’ll also add a .c class to historical computer moves — that way, we only trigger the handwriting animation for the computer’s latest move. This gives the illusion that we are only playing on a single gameboard when we are, in reality, jumping between different sections of the document.
/* Game's parent container */ .b, body:has(:target) #--------- { /* Game states */ .s { display: none; } } /* Game pieces with :target, elements with href */ :target, #--------- { width: 300px; height: 300px; / left: calc(50vw - 150px); top: calc(50vh - 150px); background-image: url(/path/to/animated/grid.gif); background-repeat: no-repeat; background-size: 100% auto; /* Display that game state and bring it to the forefront */ .s { z-index: 1; display: inline-block; } /* The player's move */ .x { z-index: 1; display: inline-block; background-image: url("data:image/svg+xml [...]"); /** shortened for brevity **/ height: 100px; width: 100px; } /* The browser's move */ circle { animation-fill-mode: forwards; animation-name: draw; animation-duration: 1s; /* Only animate the browser's latest turn */ &.c { animation-play-state: paused; animation-delay: -1s; } } }When a jump link is selected by clicking an empty square, the :target pseudo-class displays the updated game state(.s), styled so that the computer’s precalculated response makes an animated entrance (.c).
Note the special case when we start the game: We need to display the initial empty grid before the user selects any jump link. There is nothing to style with :target at the start, so we hide the initial state — with the:body:has(:target) #--------- selector — once a jump link is selected. Similarly, if you create your experiments using :target you’ll want to present an initial view before the user begins interacting with your page.
Wrapping upI won’t go into “why” we’d want to implement this in CSS instead of what might be an “easier” path with JavaScript. It’s simply fun and educational to push the boundaries of CSS. We could, for example, pull this off with the classic checkbox hack — someone did, in fact.
Is there anything interesting about using :target instead? I think so because:
- We can save games in CSS! Bookmark the URL and come back to it anytime in the state you left it.
- There’s a potential to use the browser’s Back and Forward buttons as game controls. It’s possible to undo a move by going Back in time or replay a move by navigating Forward. Imagine combining :target with the checkbox hack to create games with a time-travel mechanic in the tradition of Braid.
- Share your game states. There’s the potential of Wordle-like bragging rights. If you manage to pull off a win or a draw against the unbeatable CSS Tic Tac Toe algorithm, you could show your achievement off to the world by sharing the URL.
- It’s completely semantic HTML. The checkbox hack requires you to hide checkboxes or radio buttons, so it will always be a bit of a hack and painful horse-trading when it comes to accessibility. This approach arguably isn’t a hack since all we are doing is using jump links and divs and their styling. This may even make it — dare I say —“easier” to provide a more accessible experience. That’s not to say this is accessible right out of the box, though.
Time Travelling CSS With :target originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
Sticky Headers And Full-Height Elements: A Tricky Combination
Quite a fun article I worked on with Philip Braunen. Do you know that little bit of elasticity you get when scrolling beyond the viewport when browsing the web on a mobile device? iPhone calls it a “rubber-banding” effect. And you know it’s cool because Apple has previously fought to hold a copyright on it.
Anyway, Philip wrote into Smashing Magazine with a clever approach to mimic rubber-banding in CSS — not only for non-mobile UI but also applied to any sort of container you like.
But what about sticky headers and footers? If those have to be pinned to the container’s block edges, then how in heck do we include them in the rubber banding? Phillip’s trick is an extra div before the header, though we can get more concise markup using pseudos instead.
Sticky Headers And Full-Height Elements: A Tricky Combination originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
Quick Hit #17
“Wrapping the <label> around the <input> is fine, and is sufficient for conformance on its own, however adding explicit association with for and id is still necessary in practice.” —James Edwards
Quick Hit #17 originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
Quick Hit #16
“Never, ever hire for JavaScript framework skills. Instead, interview and hire only for fundamentals like web standards, accessibility, modern CSS, semantic HTML, and Web Components.” — Alex Russell
Quick Hit #16 originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
Quick Hit #15
Almost missed that the WP Twenty Twenty-Five theme was approved a couple weeks ago.
Quick Hit #15 originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
Quick Hit #14
Inclusive Design 24 is in 8 short days — and it’s FREE, no sign-up required!
Quick Hit #14 originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
Paragraphs
I sure do love little reminders about HTML semantics, particularly semantics that are tougher to commit to memory. Scott has a great one, beginning with this markup:
<p>I am a paragraph.</p> <span>I am also a paragraph.</span> <div>You might hate it, but I'm a paragraph too.</div> <ul> <li>Even I am a paragraph.</li> <li>Though I'm a list item as well.</li> </ul> <p>I might trick you</p> <address>Guess who? A paragraph!</address>You may look at that markup and say “Hey! You can’t fool me, only the <p> elements are “real” paragraphs!
You might even call out such elements as divs or spans being used as “paragraphs” a WCAG failure.
But, if you’re thinking those sorts of things, then maybe you’re not aware that those are actually all “paragraphs”.
It’s easy to forget this since many of those non-paragraph elements are not allowed in between paragraph tags and it usually gets all sorted out anyway when HTML is parsed.
The accessibility bits are what I always come to Scott’s writing for:
Those examples I provided at the start of this post? macOS VoiceOver, NVDA and JAWS treat them all as paragraphs ([asterisks] for NVDA, read on…). […] The point being that screen readers are in step with HTML, and understand that “paragraphs” are more than just the p element.
Paragraphs originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
Shipping Tumblr and WordPress
Didya see that Tumblr is getting a WordPress makeover? And it’s not a trivial move:
This won’t be easy. Tumblr hosts over half a billion blogs. We’re talking about one of the largest technical migrations in internet history. Some people think it’s impossible. But we say, “challenge accepted.”
Half a billion blogs. Considering that WordPress already powers somewhere around 40% of all websites (which is much, much higher than 500m) this’ll certainly push that figure even further.
I’m sure there’s at least one suspicious nose out there catching whiffs of marketing smoke though I’m amicable to the possibility that this is a genuine move to enhance a beloved platform that’s largely seen as a past relic of the Flickr era. I loved Tumblr back then. It really embraced the whole idea that a blog can help facilitate better writing with a variety of post formats. (Post formats, fwiw, are something I always wished would be a WordPress first-class citizen but they never made it out of being an opt-in theme feature). Tumblr was the first time I was able to see blogging as more than a linear chain of content organized in reverse chronological order. Blog posts are more about what you write and how you write it than they are when they’re written.
Anyway, I know jobs are a scarce commodity in tech these days and Auttomatic is looking for folks to help with the migration.
I was about to say this “could” be a neat opportunity, but nay, it’s a super interesting and exciting opportunity, one where your work is touching two of the most influential blogging platforms on the planet. I remember interviewing Alex Hollender and Jon Robson after they shipped a design update to Wikipedia and thinking how much fun and learning would come out of a project like that. This has that same vibe to me. Buuuut, make no illusions about it: it’ll be tough.
Shipping Tumblr and WordPress originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
Introducing <skelly-wc>
I created a little library at work to make those “skeleton screens” that I’m not sure anyone likes. […] We named it skellyCSS because… skeletons and CSS, I guess. We still aren’t even really using it very much, but it was fun to do and it was the first node package I made myself (for the most part).
Regardless of whether or not anyone “likes” skeleton screens, they do come up and have their use cases. And they’re probably not something you want to rebuild time and again. Great use for a web component, I’d say! Maybe Ryan can get Uncle Dave to add it to his Awesome Standalones list. 😉
The other reason I’m sharing this link is that Ryan draws attention to the Web Components De-Mystified course that Scott Jehl recently published, something worth checking out of course, but that I needed a reminder for myself.
Introducing <skelly-wc> originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
Useful Tools for Creating AVIF Images
AVIF (AV1 Image File Format) is a modern image file format specification for storing images that offer a much more significant file reduction when compared to other formats like JPG, JPEG, PNG, and WebP. Version 1.0.0 of the AVIF specification was finalized in February 2019 and released by Alliance for Open Media to the public.
You save 50% of your file size when compared to JPG and 20% compared to WebP while still maintaining the image quality.
In this article, you will learn about some browser-based tools and command-line tools for creating AVIF images.
Why use AVIF over JPGs, PNGS, WebP, and GIF?- Lossless compression and lossy compression
- JPEG suffers from awful banding
- WebP is much better, but there’s still noticeable blockiness compared to the AVIF
- Multiple color space
- 8, 10, 12-bit color depth
Jake Archibald, wrote an article a few years back on this new image format and also helped us to identify some disadvantages to compressing images, normally you should look out for these two when compressing to AVIF:
- If a user looks at the image in the context of the page, and it strikes them as ugly due to compression, then that level of compression is not acceptable. But, one tiny notch above that boundary is fine.
- It’s okay for the image to lose noticeable detail compared to the original unless that detail is significant to the context of the image.
See also: Addy Osmani at Smashing Magazine goes in-depth on using AVIF and WebP.
Browser Solutions Squoosh Screenshot of Squoosh.Squoosh is a popular image compression web app that allows you to convert images in numerous formats to other widely used compressed formats, including AVIF.
Features- File-size limit: 4MB
- Image optimization settings (located on the right side)
- Download controls – this includes seeing the size of the resulting file and the percentage reduction from the original image
- Free to use
Cloudinary’s free image-to-AVIF converter is another image tool that doesn’t require any form of code. All you need to do is upload your selected images (PNG, JPG, GIF, etc.) and it returns compressed versions of them. Its API even has more features besides creating AVIF images like its image enhancement and artificially generating filling for images.
I’m pretty sure you’re here because you’re looking for a free and fast converter. So, the browser solution should do.
Features
- No stated file size limit
- Free to use
You can find answers to common questions in the Cloudinary AVIF converter FAQ.
Command Line Solutions avif-cliavif-cli by lovell lets you take your images (PNG, JPEG, etc.) stored in a folder and converts them to AVIF images of your specified reduction size.
Here are the requirements and what you need to do:
- Node.js 12.13.0+
Install the package:
npm install avifRun the command in your terminal:
npx avif --input="./imgs/*" --output="./output/" --verbose- ./imgs/* – represents the location of all your image files
- ./output/ – represents the location of your output folder
- Free to use
- Speed of conversion can be set
You can find out about more commands via the avif-cli GitHub page.
sharpsharp is another useful tool for converting large images in common formats to smaller, web-friendly AVIF images.
Here are the requirements and what you need to do:
- Node.js 12.13.0+
Install the package:
npm install sharpCreate a JavaScript file named sharp-example.js and copy this code:
const sharp = require('sharp') const convertToAVIF = () => { sharp('path_to_image') .toFormat('avif', {palette: true}) .toFile(__dirname + 'path_to_output_image') } convertToAVIF()Where path_to_image represents the path to your image with its name and extension, i.e.:
./imgs/example.jpgAnd path_to_output_image represents the path you want your image to be stored with its name and new extension, i.e.:
/sharp-compressed/compressed-example.avifRun the command in your terminal:
node sharp-example.jsAnd there! You should have a compressed AVIF file in your output location!
Features- Free to use
- Images can be rotated, blurred, resized, cropped, scaled, and more using sharp
See also: Stanley Ulili’s article on How To Process Images in Node.js With Sharp.
ConclusionAVIF is a technology that front-end developers should consider for their projects. These tools allow you to convert your existing JPEG and PNG images to AVIF format. But as with adopting any new tool in your workflow, the benefits and downsides will need to be properly evaluated in accordance with your particular use case.
I hope you enjoyed reading this article as much as I enjoyed writing it. Thank you so much for your time and I hope you have a great day ahead!
Useful Tools for Creating AVIF Images originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
Understanding Gutenberg Blocks, Patterns, and Templates
Developers suffer in the great multitudes whom their sacred block-based websites cannot reach.
Johannes Gutenberg (probably)Long time WordPresser, first time Gutenberger here. I’m a fan even though I’m still anchored to a classic/block hybrid setup. I believe Johanes himself would be, too, trading feather pens for blocks. He was a forward-thinking 15th-century inventor, after all.
My enthusiasm for Gutenberg-ness is curbed at the theming level. I’ll sling blocks all day long in the Block Editor, but please, oh please, let me keep my classic PHP templates and the Template Hierarchy that comes with it. The separation between theming and editing is one I cherish. It’s not that the Site Editor and its full-site editing capabilities scare me. It’s more that I fail to see the architectural connection between the Site and Block Editors. There’s a connection for sure, so the failure of not understanding it is more on me than WordPress.
The WP Minute published a guide that clearly — and succinctly — describes the relationships between WordPress blocks, patterns, and templates. There are plenty of other places that do the same, but this guide is organized nicely in that it starts with the blocks as the lowest-level common denominator, then builds on top of it to show how patterns are comprised of blocks used for content layout, synced patterns are the same but are one of many that are edited together, and templates are full page layouts cobbled from different patterns and a sprinkle of other “theme blocks” that are the equivalent of global components in a design system, say a main nav or a post loop.
The guide outlines it much better, of course:
- Gutenberg Blocks: The smallest unit of content
- Patterns: Collections of blocks for reuse across your site
- Synced Patterns: Creating “master patterns” for site-wide updates
- Synced Pattern Overrides: Locking patterns while allowing specific edits
- Templates: The structural framework of your WordPress site
That “overrides” enhancement to the synced patterns feature is new to me. I’m familiar with synced patterns (with a giant nod to Ganesh Dahal) but must’ve missed that in the WordPress 6.6 release earlier this summer.
I’m not sure when or if I’ll ever go with a truly modern WordPress full-site editing setup wholesale, out-of-the-box. I don’t feel pressured to, and I believe WordPress doesn’t care one way or another. WordPress’s ultimate selling point has always been its flexibility (driven, of course, by the massive and supportive open-source community behind it). It’s still the “right” tool for many types of projects and likely will remain so as long as it maintains its support for classic, block, and hybrid architectures.
Understanding Gutenberg Blocks, Patterns, and Templates originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
Quick Hit #13
Happy birthday, Chris Coyier — and thank you for CSS-Tricks as well as everything you do at CodePen, ShopTalk, Boost, and even your personal blog!
Quick Hit #13 originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
Quick Hit #12
Giant kudos to Scott Jehl on releasing his new Web Components De-Mystified online course! Eight full hours of training from one of the best in the business.
Quick Hit #12 originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
Basic keyboard shortcut support for focused links
Eric gifting us with his research on all the various things that anchors (not links) do when they are in :focus.
Turns out, there’s a lot!
That’s an understatement! This is an incredible amount of work, even if Eric calls it “dry as a toast sandwich.” Boring ain’t always a bad thing. Let me simply drop in a pen that Dave put together pulling all of Eric’s findings into a table organized to compare the different behaviors between operating systems — and additional tables for each specific platform — because I think it helps frame Eric’s points.
CodePen Embed FallbackThat really is a lot! But why on Earth go through the trouble of documenting all of this?
All of the previously documented behavior needs to be built in JavaScript, since we need to go the synthetic link route. It also means that it is code we need to set aside time and resources to maintain.
That also assumes that is even possible to recreate every expected feature in JavaScript, which is not true. It also leaves out the mental gymnastics required to make a business case for prioritizing engineering efforts to re-make each feature.
There’s the rub! These are the behaviors you’re gonna need to mimic and maintain if veering away from semantic, native web elements. So what Eric is generously providing is perhaps an ultimate argument against adopting frameworks — or rolling some custom system — that purposely abstract the accessible parts of the web, often in favor of DX.
As with anything, there’s more than meets the eye to all this. Eric’s got an exhaustive list at the end there that calls out all the various limitations of his research. Most of those notes sound to me like there are many, many other platforms, edge cases, user agent variations, assistive technologies, and considerations that could also be taken into account, meaning we could be responsible for a much longer list of behaviors than what’s already there.
And yes, this sweatshirt is incredible. Indeed.
Basic keyboard shortcut support for focused links originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.
Callbacks on Web Components?
A gem from Chris Ferdinandi that details how to use custom events to hook into Web Components. More importantly, Chris dutifully explains why custom events are a better fit than, say, callback functions.
With a typical JavaScript library, you pass callbacks in as part of the instantiate process. […] Because Web Components self-instantiate, though, there’s no easy way to do that.
There’s a way to use callback functions, just not an “easy” way to go about it.
JavaScript provides developers with a way to emit custom events that developers can listen for with the Element.addEventListener() method.
We can use custom events to let developers hook into the code that we write and run more code in response to when things happen. They provide a really flexible way to extend the functionality of a library or code base.
Don’t miss the nugget about canceling custom events!
Callbacks on Web Components? originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.