Diving into the ::before and ::after Pseudo-Elements / Coder’s Block
A thorough deep dive into generated content in CSS.
A thorough deep dive into generated content in CSS.
A minimal style sheet that applies some simple rules to HTML elements so you can take a regular web page and drop in this CSS to spruce it up a bit.
You’re not going to get a Webby Award or thousands of views on Codepen for how amazingly crafted your HTML is. You’ll need to be OK going unrecognized for your work. But know that every time I use a screen reader or keyboard on a site and it works correctly, I have a little spark of joy.
While a handful of form controls can be easily styled by CSS, like the button element, most form controls fall into a bucket of either requiring hacky CSS or are still unable to be styled at all by CSS.
Despite form controls no longer taking a style or technical dependency on the operating system and using modern rendering technology from the browser, developers are still unable to style some of the most used form control elements such as
select
. The root of this problem lies in the way the specification was originally written for form controls back in 1995.
Stephanie goes back in time to tell the history of form controls on the web, and how that history has led to our current frustrations:
The current state of working with controls on the modern web is that countless developer hours are being lost to rewriting controls from scratch, as custom elements due to a lack of flexibility in customizability and extensibility of native form controls. This is a massive gap in the web platform and has been for years. Finally, something is being done about it.
Amen!
I think this is quite beautiful—no need to view source; the style sheet is already in the document.
A really great one-page guide to HTML from Bruce. I like his performance-focused intro:
If your site is based on good HTML, it will load fast. Browsers incrementally render HTML—that is, they will display a partially downloaded web page to the user while the browser awaits the remaining files from the server.
Modern fashionable development techniques, such as React, require a lot of JavaScript to be sent to the user. When it’s all downloaded, the user’s device must parse and execute the JavaScript before it can even start to construct the page. On a slow network, or on a cheaper, low-powered device, this can result in an excruciatingly slow load and is a heavy drain on the battery.
Just today I was discussing with Trys and Cassie why developers tend to create bespoke JavaScript-driven components rather than using the elements that browsers give us for free. It all comes down to the ability to style the user interface.
Here, Brian proposes a kind of minimum viable web component that handles logic like keyboard control and accessibility, but leaves the styling practically untouched. Check out his panel-set demo of a tabbed interface.
I really, really like the way that it wraps existing content. If the web component fails for any reason, the content is still available. So the web component is a progressive enhancement:
An experimental custom element that wraps plain-old HTML (view the source) and decorates function, keyboard handling, accessibility information.
Here’s one simple, practical way to make apps perform better on mobile devices: always configure HTML input fields with the correct
type
,inputmode
, andautocomplete
attributes. While these three attributes are often discussed in isolation, they make the most sense in the context of mobile user experience when you think of them as a team.
This is an excellent deep dive with great advice:
You may think that you are familiar with the basic
autocomplete
options, such as those that help the user fill in credit card numbers or address form fields, but I’d urge you to review them to make sure that you are aware of all of the options. The spec lists over 50 values!
Amber runs through some HTML elements that help you provide semantic information—and accessibility—for your website: headings, paragraphs, lists, and more:
You may be aware that ARIA roles are often used with HTML elements. I haven’t written about them here, as it’s good to see how HTML written without ARIA can still be accessible.
Some solid research here. Turns out that using input type=”text” inputmode=”numeric” pattern="[0-9]*"
is probably a better bet than using input type="number"
.
Chris takes two side-by-side deep dives; one into the a
element, the other into the button
element.
Even if you think you already know those elements well, I bet there’ll be something new here for you. Like, did you know that the button
element can have form over-riding attributes like formaction
, formenctype
, formmethod
, formnovalidate
, and formtarget
?
At the risk of being a broken record; HTML really needs
<accordion>
,<tabs>
,<dialog>
,<dropdown>
, and<tooltip>
elements. Not more “low-level primitives” but good ol’ fashioned, difficult-to-get-consensus-on elements.
Hear, hear!
I wish browsers would prioritize accessibility improvements over things like main thread scheduling optimization to unblock tracking pixels and the Sisyphean task of competing with native.
If we really want to win, let’s make it easy for everyone to access the Web.
A one-stop shop for all the metacrap you can put in the head
of your HTML documents.
Test your knowledge of the original version of HTML—how many elements can you name?
Some very smart ideas in here for resetting default browser styles, like only resetting lists that have classes applied to them:
ul[class],
ol[class] {
padding: 0;
}
I select only lists that do have a
class
attribute because if a plain ol’<ul>
or<ol>
gets used, I want it to look like a list. A lot of resets, including my previous ones, aggressively remove that.
Greg has done a lot of research into developer frustrations with customising form controls.
My current thinking in this space, and I know some folks will find this controversial, but I think we should completely standardize in-page form controls with no limitations on their styling capabilities. What do I mean by in-page controls? I am referring to any form control or component that is rendered within the content process. This standardization would include the sub-parts and their related states and how these are exposed (probably through CSS psuedo classes or HTML attributes). This will enable the shadow-dom to be encapsulated while providing web developers with a consistent experience to adjust to match their brand and needs of their site/application.
What you see really is what you get. I like this style!
I’ll be in my bunk.
I’ve often said that the goal of a good library should be to make itself redundant. jQuery is the poster child for that, and this article points to web components as the way to standardise what’s already happening in JavaScript frameworks:
Remember when
document.querySelector
first got wide browser support and started to end jQuery’s ubiquity? It finally gave us a way to do natively what jQuery had been providing for years: easy selection of DOM elements. I believe the same is about to happen to frontend frameworks like Angular and React.
The article goes on to give a good technical overview of custom elements, templates, and the Shadow DOM, but I was surprised to see it making reference to the is
syntax for extending existing HTML elements—I’m pretty sure that that is, sadly, dead in the water.
Cassie posted a neat tiny lesson that she’s written a reduced test case for.
Here’s the situation…
CSS custom properties are fantastic. You can drop them in just about anywhere that a property takes a value.
Here’s an example of defining a custom property for a length:
:root {
--my-value: 1em;
}
Then I can use that anywhere I’d normally give something a length:
.my-element {
margin-bottom: var(--my-value);
}
I went a bit overboard with custom properties on the new Patterns Day site. I used them for colour values, font stacks, and spacing. Design tokens, I guess. They really come into their own when you combine them with media queries: you can update the values of the custom properties based on screen size …without having to redefine where those properties are applied. Also, they can be updated via JavaScript so they make for a great common language between CSS and JavaScript: you can define where they’re used in your CSS and then update their values in JavaScript, perhaps in response to user interaction.
But there are a few places where you can’t use custom properties. You can’t, for example, use them as part of a media query. This won’t work:
@media all and (min-width: var(--my-value)) {
...
}
You also can’t use them in generated content if the value is a number. This won’t work:
:root {
--number-value: 15;
}
.my-element::before {
content: var(--number-value);
}
Fair enough. Generated content in CSS is kind of a strange beast. Eric delivered an entire hour-long talk at An Event Apart in Seattle on generated content.
But Cassie found a workaround if the value you want to put into that content
property is numeric. The CSS counter
value is a kind of generated content—the numbers that appear in front of ordered list items. And you can control the value of those numbers from CSS.
CSS counters work kind of like variables. You name them and assign values to them using the counter-reset
property:
.my-element {
counter-reset: mycounter 15;
}
You can then reference the value of mycounter
in a content
property using the counter
value:
.my-element {
content: counter(mycounter);
}
Cassie realised that even though you can’t pass in a custom property directly to generated content, you can pass in a custom property to the counter-reset
property. So you can do this:
:root {
--number-value: 15;
}
.my-element {
counter-reset: mycounter var(--number-value);
content: counter(mycounter);
}
In a roundabout way, this allows you to use a custom property for generated content!
I realise that the use cases are pretty narrow, but I can’t help but be impressed with the thinking behind this. Personally, I would’ve just read that generated content doesn’t accept custom properties and moved on. I would’ve given up quickly. But Cassie took a step back and found a creative pass-the-parcel solution to the problem.
I feel like this is a hack in the best sense of the word: a creatively improvised solution to a problem or limitation.
I was trying to display the numeric value stored in a CSS variable inside generated content… Turns out you can’t do that. But you can do this… codepen.io/cassie-codes/p… (not saying you should, but you could)