A Friendly Introduction to SVG • Josh W. Comeau
A fantastic explanation of the building blocks of SVG, illustrated—as always—with Josh’s interactive examples.
A fantastic explanation of the building blocks of SVG, illustrated—as always—with Josh’s interactive examples.
A UI library for people who love HTML, powered by modern CSS and Web Components.
A great talk by Matthias on what you can do with web standards today!
I’ve been thinking about the kind of CSS I write by default when I start a new project.
Some of it is habitual. I now use logical properties automatically. It took me a while to rewire my brain, but now seeing left
or top
in a style sheet looks wrong to me.
When I mentioned this recently, I had some pushback from people wondering why you’d bother using logical properites if you never planned to translate the website into a language with a different writing system. I pointed out that even if you don’t plan to translate a web page, a user may still choose to. Using logical properties helps them. From that perspective, it’s kind of like using user preference queries.
That’s something else I use by default now. If I’ve got any animations or transitions in my CSS, I wrap them in prefers-reduced-motion: no-preference
query.
For instance, I’m a huge fan of view transitions and I enable them by default on every new project, but I do it like this:
@media (prefers-reduced-motion: no-preference) {
@view-transition {
navigation: auto;
}
}
I’ll usually have a prefers-color-scheme
query for dark mode too. This is often quite straightforward if I’m using custom properties for colours, something else I’m doing habitually. And now I’m starting to use OKLCH for those colours, even if they start as hexadecimal values.
Custom properties are something else I reach for a lot, though I try to avoid premature optimisation. Generally I wait until I spot a value I’m using more than two or three times in a stylesheet; then I convert it to a custom property.
I make full use of clamp()
for text sizing. Sometimes I’ll just set a fluid width on the html
element and then size everything else with em
s or rem
s. More often, I’ll use Utopia to flow between different type scales.
Okay, those are all features of CSS—logical properties, preference queries, view transitions, custom properties, fluid type—but what about actual snippets of CSS that I re-use from project to project?
I’m not talking about a CSS reset, which usually involves zeroing out the initial values provided by the browser. I’m talking about tiny little enhancements just one level up from those user-agent styles.
Here’s one I picked up from Eric that I apply to the figcaption
element:
figcaption {
max-inline-size: max-content;
margin-inline: auto;
}
That will centre-align the text until it wraps onto more than one line, at which point it’s no longer centred. Neat!
Here’s another one I start with on every project:
a:focus-visible {
outline-offset: 0.25em;
outline-width: 0.25em;
outline-color: currentColor;
}
That puts a nice chunky focus ring on links when they’re tabbed to. Personally, I like having the focus ring relative to the font size of the link but I know other people prefer to use a pixel size. You do you. Using the currentColor
of the focused is usually a good starting point, thought I might end up over-riding this with a different hightlight colour.
Then there’s typography. Rich has a veritable cornucopia of starting styles you can use to improve typography in CSS.
Something I’m reaching for now is the text-wrap
property with its new values of pretty
and balance
:
ul,ol,dl,dt,dd,p,figure,blockquote {
hanging-punctuation: first last;
text-wrap: pretty;
}
And maybe this for headings, if they’re being centred:
h1,h2,h3,h4,h5,h6 {
text-align: center;
text-wrap: balance;
}
All of these little snippets should be easily over-writable so I tend to wrap them in a :where()
selector to reduce their specificity:
:where(figcaption) {
max-inline-size: max-content;
margin-inline: auto;
}
:where(a:focus-visible) {
outline-offset: 0.25em;
outline-width: 0.25em;
outline-color: currentColor;
}
:where(ul,ol,dl,dt,dd,p,figure,blockquote) {
hanging-punctuation: first last;
text-wrap: pretty;
}
But if I really want them to be easily over-writable, then the galaxy-brain move would be to put them in their own cascade layer. That’s what Manu does with his CSS boilerplate:
@layer core, third-party, components, utility;
Then I could put those snippets in the core
layer, making sure they could be overwritten by the CSS in any of the other layers:
@layer core {
figcaption {
max-inline-size: max-content;
margin-inline: auto;
}
a:focus-visible {
outline-offset: 0.25em;
outline-width: 0.25em;
outline-color: currentColor;
}
ul,ol,dl,dt,dd,p,figure,blockquote {
hanging-punctuation: first last;
text-wrap: pretty;
}
}
For now I’m just using :where()
but I think I should start using cascade layers.
I also want to start training myself to use the lh
value (line-height) for block spacing.
And although I’m using the :has()
selector, I don’t think I’ve yet trained my brain to reach for it by default.
CSS has sooooo much to offer today—I want to make sure I’m taking full advantage of it.
This is clever: putting CSS inside a noscript
element to hide anything that requires JavaScript.
There’s a new proposal for giving developers more control over styling form controls. I like it.
It’s clearly based on the fantastic work being done by the Open UI group on the select
element. The proposal suggests that authors can opt-in to the new styling possibilities by declaring:
appearance: base;
So basically the developer is saying “I know what I’m doing—I’m taking the controls.” But browsers can continue to ship their default form styles. No existing content will break.
The idea is that once the developer has opted in, they can then style a number of pseudo-elements.
This proposal would apply to pretty much all the form controls you can think of: all the input
types, along with select
, progress
, meter
, buttons and more.
But there’s one element more that I wish were on the list:
legend
I know, technically it’s not a form control but legend
and fieldset
are only ever used within forms.
The legend
element is notoriously annoying to style. So a lot of people just don’t bother using it, which is a real shame. It’s like we’re punishing people for doing the right thing.
Wouldn’t it be great if you, as a developer, had the option of saying “I know what I’m doing—I’m taking the controls”:
legend {
appearance: base;
}
Imagine if that nuked the browser’s weird default styles, effectively turning the element into a span
or div
as far as styling is concerned. Then you could style it however you wanted. But crucially, if browsers shipped this, no existing content would break.
The shitty styling situation for legend
(and its parent fieldset
) is one of those long-standing annoyances that seems to have fallen down the back of the sofa of browser vendors. No one’s going to spend time working on it when there are more important newer features to ship. That’s why I’d love to see it sneak in to this new proposal for styling form controls.
I was in Amsterdam last week. Just like last year I was there to help out Vasilis’s students with a form-based assignment:
They’re given a PDF inheritance-tax form and told to convert it for the web.
Yes, all the excitement of taxes combined with the thrilling world of web forms.
(Side note: this time they were told to style it using the design system from the Dutch railway because the tax office was getting worried that they were making phishing sites.)
I saw a lot of the same challenges again. I saw how students wished they could specify a past date or a future date in a date picker without using JavaScript. And I saw them lamenting the time they spent styling legend
s that worked across all browsers.
Right now, Mason Freed has an open issue on the new proposal with his suggestion to add some more elements to consider. Both legend
and fieldset
are included. That gets a thumbs-up from me.
- Springy easing with
linear()
- Typed custom properties
- View transitions for page navigation
- Transition animation for
dialog
andpopover
- Transition animation for
details
- Animated adaptive gradient text
I like the approach here: logical properties and sensible default type and spacing.
Picture me holding Trys back and telling him, “Leave it alone, mate, it’s not worth it!”
This is a very handy piece of work by Rich:
The idea is to set sensible typographic defaults for use on prose (a column of text), making particular use of the font features provided by OpenType. The main principle is that it can be used as starting point for all projects, so doesn’t include design-specific aspects such as font choice, type scale or layout (including how you might like to set the line-length).
Speaking of zines, I really like Benjamin’s ideas about a web-first indie web zine: using print stylesheets with personal websites to make something tangible but webby.
I had a lot of fun making the website for Patterns Day.
If you’re interested in the tech stack, here’s what I used:
Actually, technically it’s all HTML because the styles are inside a style
element rather than a separate style sheet, but you know what I mean. Also, there is technically some JavaScript but all it does is register a service worker that takes care of caching and going offline.
I didn’t use any build tools. There was no pipeline. There is no node_modules
folder filling up my hard drive. Nothing was automated. The website was hand-crafted the long hard stupid way.
I started with the content. I wrote out the words and marked them up with the most appropriate HTML elements.
Time to layer on the presentation.
For the design, I turned to Michelle for help. I gave her a brief, describing the vibe of the conference, and asked her to come up with an appropriate visual language.
Crucially, I asked her not to design a website. Instead I asked her to think about other places where this design language might be used: a poster, social media, anything but a website.
Partly I was doing this for my own benefit. If you give me a pixel-perfect design for a web page and tell me to code it up, either I won’t do it or I won’t enjoy it. I just don’t get any motivation out of that kind of direct one-to-one translation.
But give me guardrails, give me constraints, give me boundary conditions, and off I go!
Michelle was very gracious in dealing with such a finicky client as myself (“Can you try this other direction?”, “Hmm… I think I preferred the first one after all!”) She delivered a colour palette, a type scale, typeface choices, and some wonderful tiling patterns …it is Patterns Day after all!
With just a few extra lines of CSS, the basic typography was in place.
I started layering on the colours. Even though this was a one-page site, I still made liberal use of custom properties in the CSS. It just feels good to be able to update one value and see the results, well …cascade.
I had a lot of fun with the tiling background images. SVG was the perfect format for these. And because the tiles were so small in file size, I just inlined them straight into the CSS.
By this point, I felt like I was truly designing in the browser. Adjusting spacing, playing around with layout, and all that squishy stuff. Some of the best results came from happy accidents—the way that certain elements behaved at certain screen sizes would lead me into little experiments that yielded interesting results.
I’m not sure it’s possible to engineer that kind of serendipity in Figma. Figma was the perfect tool for exploring ideas around the visual vocabulary, and for handing over design decisions around colour, typography, and texture. But when it comes to how the content is going to behave on the World Wide Web, nothing beats a browser for fidelity.
By this point I was really sweating the details, like getting the logo just right and adjusting the type scale for different screen sizes. Needless to say, Utopia was a godsend for that.
I was also checking back in with Michelle to get her take on design decisions I was making.
I could’ve kept tinkering but the diminishing returns were a sign that it was time to put this out into the world.
It felt really good to work on a web page like this. It felt like I was getting my hands into the soil of the web. I don’t think it’s an accident that the result turned out to be very performant.
Getting hands-on like this stops me from getting rusty. And honestly, working with CSS these days is a joy. There’s such power to be had from using var()
in combination with functions like calc()
and clamp()
. Layout is a breeze with flexbox
and grid
. Browser differences are practically non-existent. We’ve never had it so good.
Here’s something I noticed about my relationship to CSS; my brain has finally made the switch to logical properties. Now if I’m looking at some CSS and I see left
, right
, top
, or bottom
, it looks like a bug to me. Those directional properties feel loaded with assumptions whereas logical properties feel much more like working with the grain of the web.
Oh, this is a nice addition to the Utopia set of tools: when you don’t need a full-on type scale but you still want to figure out fluid clamp()
values, the clamp calculator has you covered.
It’s got permalinks too!
A solid update to Andy’s four-years old CSS reset. Best of all, every single line comes with an explanation. So if you don’t like the reasoning, don’t use that line.
This is handy—a collection of font stacks using system fonts. You can see which ones are currently installed on your machine too.
The most performant web font is no web font.
I love print stylesheets but I was today years old when I found out that print-color-adjust
exists.
I agree with the reasoning here—a new display
value would be ideal.
Ever get the urge to style a good document?
No? Just me, then.
Well, the urge came over me recently so I started styling this single-page site:
A Few Notes On The Culture by Iain M Banks
I’ve followed this document across multiple locations over the years. It started life as a newsgroup post on rec.arts.sf.written in 1994. Ken McLeod published it there on Iain M Banks’s behalf.
The post complements the epic series of space opera books that Iain M Banks set in the anarcho-utopian society of The Culture. It’s a fascinating piece of world building, as well as an insight into the author’s mind.
I first became aware of it many few years later, after a copy had been posted to the web. That URL died, but Adrian Hon kept a copy on his site. Lots of copies keep stuff safe, so after contemplating linkrot, I made a copy on this site too.
But I recently thought that maybe it deserved a bit of art direction, so I rolled up my sleeves and started messing around, designing in the browser and following happy little accidents.
The finished result is still fairly sparse. It’s still entirely text, except for a background image that shows up if your screen is wide enough. That image of a planet originally started as an infra-red snapshot of Jupiter by the James Webb Space Telescope that I worked over until it was unrecognisable.
The text itself is the main focus of the design though. I knew I wanted to play around with a variable font. Mona Sans from Github was one of the first ones I tried and I found it instantly suitable. I had a lot of fun playing with different weights and widths.
After a bit of messing around, I realised that the heading styles were reminding me of some later reissues of The Culture novels, so I leant into that, deliberately styling the byline to resemble the treatment of the author’s name on those book covers.
There isn’t all that much CSS. I’ve embedded it in the head of the HTML rather than linking to a separate style sheet, so feel free to view source and poke around in there. You’ll see that I’m making liberal use of custom properties, the clamp function, and logical properties.
Originally I had a light mode and dark mode but I found that the dark mode was much more effective so I ditched the lighter option.
I did make sure to include some judicious styles for print, so if you fancy reading on paper, it should print out nicely.
Oh, and of course it’s a progressive web app that works offline.
I didn’t want to mess with the original document other than making some typographic tweaks to punctuation, but I wanted to break up the single wall of text. I wasn’t about to start using pull quotes on the web so in the end I decided to introduce some headings that weren’t in the original document:
If your browser viewport is tall enough, the heading for the current section you’re reading will remain sticky as you scroll. No JavaScript required.
I’m pretty pleased with how this little project turned out. It was certainly fun to experiment with fluid type and a nice variable font.
I can add this to my little collection of single-page websites I’ve whittled over the years:
Hear, hear!
If you have even a passing knowledge of CSS, I encourage you to experiment with its possibilities.