Your browser may have trouble rendering this page. See supported browsers for more information.

This page shows the source for this entry, with WebCore formatting language tags and attributes highlighted.

Title

CSS and HTML Toolbox 2021

Description

Over the last four months, I've been collecting interesting HTML/CSS techniques and ideas. <ol> I'm planning a bit of a make-over of the earthli style and stylesheets to replace some older cruft with more modern, simpler implementations. I'm planning a new curriculum for the JavaScript class I'll be teaching again this coming winter. </ol> For both of these goals, I'm focusing on leveraging as much of the power of the browser---especially CSS/HTML---as possible without getting mired in too much JavaScript or client-side libraries. To that end, I've collected the stuff I learned and would like to use in a hopefully semi-readable and searchable format. I tried to split it into coherent sections with supporting information and links. YMMV. <h>Guides and Resources</h> The following guides/manuals contain a wealth of information. <dl dt_class="field"> <a href="https://developer.mozilla.org/en-US/docs/Web/CSS">MDN CSS</a> MDN is definitely the OG of web sites, with amazing examples and in-depth documentation of everything HTML and CSS. I have n idea how they stay so up-to-date or who pays for it, but it's amazing and much-appreciated <a href="https://www.w3schools.com/css/">W3Schools</a> This site is also very complete and, while it doesn't have as much description or documentation as MDN, it has a lot of interactive samples---check out the animation and transform ones---and is easy to browse. <a href="https://css-tricks.com/">CSS-Tricks</a> This site has a lot of in-depth articles on various CSS features by various authors. You can find an in-depth article for any of the features discussed below. <a href="https://web.dev/">web.dev</a> This site is run by (sponsored by?) Google and it contains a ton of articles and videos and tutorials for taking advantage of the cutting edge of web technology, with an eye toward using advanced features common to all browsers, but also introducing some of the stuff that Chrome has that hasn't been fully adopted yet. <a href="https://almanac.httparchive.org/en/2020/css">Web Almanac By HTTP Archive</a> This is an interesting guide that shows usage statistics for certain features. It's enormous and shows an insane amount of detail about e.g. how many sites use flexbox or grid. <a href="https://2020.stateofcss.com/en-US/features/">State of CSS</a> In particular for this article, you can check out the usage level of specific <a href="https://2020.stateofcss.com/en-US/features/">features</a>. This list is definitely worth a look, as a supplement to the features I outline below. <a href="https://caniuse.com/">CanIUse</a> While MDN also shows you the browser support for features, this site is very searchable and includes links for a tremendous amount of supporting information about quirks and flags for cutting-edge features. </dl> <h>Complexity</h> The article <a href="https://timseverien.com/posts/2020-12-06-what-makes-css-hard-to-master/">What Makes CSS Hard To Master</a> has several interesting examples, but it mostly boils down to: "HTML documents are complex programs". It's always been difficult to tell which styles are applied when---it's a near-miracle that browsers can untangle the myriad ways that style rules interact with an ever-changing DOM and viewport size <i>correctly</i> to say nothing of doing so with such sheer <i>alacrity</i>. There are selectors, media queries, related properties (e.g. <c>position</c>), CSS Properties, and much more and all of it <i>cascades</i> with inheritance everywhere. At least most browsers now handle this similarly with predictable performance. A tremendous amount of content is generated dynamically using layers of framework code, either on the server or the client. Any one of these moving parts could introduce a seemingly innocuous change that breaks the entire layout or inheritance (e.g. when a component introduces a wrapping <c>
</c> somewhere, either where it's flatly invalid (e.g. a table) or where it's just unwanted (e.g. in a sequence of flexing containers, where the new container does not flex). To control this chaos, most designers and developers impose self-discipline and use guidelines to avoid confusion while still allowing them to leverage the power of CSS to be able to do what they want. From the article linked above, <bq>I think mastering CSS comes down to having a good amount of knowledge about it, recognising the subtle dependencies between different declarations, rules, and the DOM, understanding how they make your CSS complex, and how to best avoid them.</bq> Congratulations: you've just described programming at anything but a trivial level of complexity. If a tool has power, then you have to understand it in order to avoid hurting yourself with it. That's why "everyone codes" is a lost cause doomed to end in failure, broken dreams, and embarrassed disappointment, like so many other quixotic attempts to ignore immanent complexity. CSS is a moving target. Things that used to be difficult are now easy.<fn> But that's the nature of the game: someone is going to abstract away the thing you spent time learning and make it easier for everyone else. That is the nature of abstraction and frameworks. If the new thing (e.g. <c>grid</c>) replaces the old thing (e.g. <c>float</c>) <i>well</i> and you have <i>time</i> and <i>budget</i> to use the new thing <i>and</i> it's a <i>priority</i> then, by all means, upgrade to use the new technique and pay down some technical debt, while hopefully gaining some flexibility. <h>Generators</h> While CSS generators---pre-processors like LESS and SASS---are invaluable, they also introduce another layer of abstraction where code is generated for the developer---sometimes with unpredictable results. The latest versions of CSS have included some of the features introduced in these generators. Vendor prefixes are less necessary than they used to be; CSS properties and variables and <c>eval()</c> (as well as other standard functions) allow a flexibility beyond even that offered by pre-processor variables. Color and transformation and animation functions are standard now. <h>Standard Layouts</h> Check out the site <a href="https://smolcss.dev/" author="Stephanie Eckles">SmolCSS</a> for a long list of common layouts, like: <ul> Responsive CSS Grid Modern Centering Avatar List Component Stack Layout And much more... </ul> It's called "smol" because almost all of them do a <i>lot</i> of heavy lifting with very few lines of CSS. <img src="{att_link}smol.png" href="{att_link}smol.png" align="none" caption="Smol Grid Layout" scale="25%"> <h>Selectors</h> The article <a href="https://moderncss.dev/guide-to-advanced-css-selectors-part-one/" source="Modern CSS" author="Stephanie Eckles">Guide to Advanced CSS Selectors - Part One</a> is a good overview with good illustrations and some selectors I'd never heard of, like <a href="https://moderncss.dev/guide-to-advanced-css-selectors-part-one/#general-sibling-combinator">General Sibling Combinator</a>, which <iq>[f]or example, <c>p ~ img</c> would style all images that are located somewhere after a paragraph provided they share the same parent.</iq> That whole site is beautiful and exhibits an absolute mastery of CSS. Check out the use of the <c>skew</c> <c>transform</c> for the cards at the bottom of the page or for the <a href="https://moderncss.dev">whole series</a>. The rainbow gradients on the <c>:before</c> and <c>:after</c> borders and backgrounds are a great idea and well-executed. The excellent tutorial <a href="https://codersblock.com/blog/diving-into-the-before-and-after-pseudo-elements/" source="Coder's Block" author="Will Boyd">Diving into the ::before and ::after Pseudo-Elements</a> is an absolute treasure trove of information, including how to use the <c>::before</c>/<c>::after</c> pseudo-elements to insert content, but also noting how a classic use of <c>::after</c> can now be replaced with <c>display: flow-root</c> (the modern <i>clearfix</i>). He also covers <c>::markers</c>. The article <a href="https://www.bram.us/2021/03/19/three-important-things-you-should-know-about-css-is/" source="Bramus">Three important things you should know about CSS :is()</a> gives a few caveats but also shows the power of this operator to reduce CSS clutter (along with the up-and-coming <i>nesting</i> feature described <a href="#nesting">below</a>). You can use <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:where" source="MDN"><c>where()</c></a> instead of <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:is" source="MDN"><c>is()</c></a> to keep the specificity contribution of the clause neutral. The <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:has" source="MDN"><c>has()</c></a> selector function is defined, but isn't available anywhere. Combine any of these with <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:not" source="MDN"><c>not()</c></a> for even more powerful selectors. <h>Properties</h> The article <a href="https://webplatform.news/issues/2020-12-04" source="Web Platform News">CSS custom properties are not variables</a> explains a common misconception about CSS "variables". <bq>A custom property is not a variable, but it defines a variable. Any property can use <i>variables</i> with the <c>var()</c> function whose values are defined by their associated custom <i>properties</i>. [...] This distinction is useful because it allows us to talk about “variables with fallback values” (a custom property like any other property cannot have a fallback value) and “properties using variables” (a property cannot use a custom property)</bq> Another great article is <a href="https://www.joshwcomeau.com/css/styled-components/" author="Josh W. Comeau">The styled-components Happy Path</a>. which discusses styling with CSS properties in React components. In it, he references another article of his, <a href="https://www.joshwcomeau.com/css/css-variables-for-react-devs/'">CSS Variables in React tutorial</a>, which is more of an introduction to some of the techniques he works with in the first article. You commonly properties with default values on the <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/:root" source="MDN">:root pseudo-selector</a>.<fn> The article <a href="https://codersblock.com/blog/what-can-you-put-in-a-css-variable/">What Can You Put in a CSS Variable?</a> shows a lot of nice uses of CSS properties, variables, and <a href="https://www.w3schools.com/csSref/css_functions.asp" source="W3Schools">functions</a>. CSS Properties can basically hold anything you want: text, concatenated strings, references to variables, images via urls, a single value, multiple values, etc.<fn> <bq>Some properties, like <c>background</c> and <c>box-shadow</c>, can take a list of things. You can use a CSS variable as a single item in the list, a sublist of the list, or the entire list.</bq> As mentioned above, declaring colors is one of the primary uses of a CSS pre-processor language. CSS Properties handle this job very nicely, without preprocessing and also with full recalculation at runtime.<fn> The <a href="https://codepen.io/lonekorean/pen/PoGNxjE">demo</a> with the set of animated RGB sliders that control the color of a swatch is worth the price of admission. All without any JavaScript at all. Smooth as butter. As a practical application, the article <a href="https://www.bram.us/2021/02/01/make-the-page-count-of-a-3d-book-visible-using-css-custom-properties/">Make the page count of a 3D book visible using CSS Custom Properties</a> shows how you can use CSS to make a "book" out of a div and a cover image, transforming it in 3D-space and then using a CSS property to determine how many "pages" it looks like it has. <img src="{att_link}screen_shot_2021-02-01_at_22.10.37.png" href="{att_link}screen_shot_2021-02-01_at_22.10.37.png" align="none" caption="Book with code" scale="25%"> <a href="https://jsbin.com/tosikapope/edit?html,css,output">You can play with a demo here.</a> You can find a simpler and very straightforward demo in the article <a href="https://christianheilmann.com/2021/02/08/sharing-data-between-css-and-javascript-using-custom-properties/" author="Christian Heilmann">Sharing data between CSS and JavaScript using custom properties</a>, which shows how to use CSS properties with a few lines of JavaScript to follow the cursor in your document. <a href="https://ishadeed.com/article/practical-css-variables/" author="Ahmad Shadeed">Practical Use Cases For CSS Variables</a> provides many, many short examples and ideas for using custom properties as an abstraction instead of setting one or more standard properties directly. <info><b>Future work:</b> See <a href="#property_proposals">below</a> for a discussion of proposed but not yet supported extensions and uses of CSS Properties. </info> <h>(Custom) Media Queries</h> The article <a href="https://polypane.app/blog/the-complete-guide-to-css-media-queries/">The complete guide to CSS media queries</a> is a great overview of how media queries work, but also how they've changed recently for those who've gotten accustomed to them over the years. For example, the section <a href="https://polypane.app/blog/the-complete-guide-to-css-media-queries/#new-notations-in-media-query-levels-4-and-5">New notations in Media query levels 4 and 5</a> shows how ranges are easier, how you can now use <c>or</c>, the <c>not()</c> function, and <i>custom media queries</i>, which allows you to basically make aliases for media query combinations that you need to use in several places. <code> /* Define your custom media query */ @custom-media --small-screen (max-width: 768px); /* Then use it somewhere in your stylesheet */ @media (--small-screen) { } /* You can also combine it with other media features */ @media (--small-screen) and (pointer: fine) { /* styling for small screens with a stylus */ } </code> <h>Gradient Overlays</h> The article <a href="https://ishadeed.com/article/handling-text-over-image-css/" author="Ahmad Shadeed">Handling Text Over Images in CSS</a> gives a wonderful overview with many examples on how to use gradient overlays on images to make overlay text readable for all types of images. At the end, you can see how many sites are using this (including YouTube for its overlay video controls). See also the <a href="https://moderncss.dev">gradients</a> used in borders (hover over a "card"), headers, and other elements in the ModernCSS tutorial. <h>Animations & Transitions</h> Check out <a href="https://www.bram.us/2021/01/29/animating-a-css-gradient-border/">Animating a CSS Gradient Border</a>, which has <i>no JavaScript</i>. It leverages a newer feature of Chrome-based renderers to avoid writing a lot of keyframe boilerplates, but it's all in CSS. You <i>could</i> write it all in bog-standard CSS. Another example is a slide show written with only HTML and CSS. You can keep all slides in a single document and make animated transitions between them. See <a href="https://www.bram.us/2021/01/24/how-to-play-and-pause-css-animations-with-css-custom-properties/">How to Play and Pause CSS Animations with CSS Custom Properties</a> for ideas. The article <a href="https://www.joshwcomeau.com/animation/css-transitions/">An Interactive Guide to CSS Transitions</a> provides a lot of background and interactive examples of how transitions work and how you can influence their behavior. CSS animations apply to many, many properties---in all modern browsers---as detailed in the article <a href="https://codersblock.com/blog/the-surprising-things-that-css-can-animate/" source="Coder's Block" author="Will Boyd">The Surprising Things That CSS Can Animate</a>, which shows how easy it is to animate box-shadows (for a "pulsating" effect) or even z-order, with a few other properties, to animate two items "switching places" in a very intuitive way---all <i>without</i> JavaScript. <h>Tooltips</h> The article <a href="https://www.bram.us/2020/12/28/cooltipz-css-pure-css-customisable-tooltips/" author="Bramus van Damme">Cooltipz.css — Pure CSS Customisable Tooltips</a> includes a good demonstration of <a href="https://cooltipz.jackdomleo.dev">Cooltipz</a>. This library uses very modern, but well-supported techniques to place and format tooltips or flyouts (for non-desktop browsers). <h>Shapes</h> <a href="https://ishadeed.com/article/clip-path/">Understanding Clip Path in CSS</a> shows how to work with the standard shape functions and combinators and the <c>clip-path</c> property to make pure-CSS non-rectangular accents and effects that run on all modern browsers. The article <a href="https://responsibleweb.app" author="Joy Heron">Responsible Web Applications</a> is an absolutely lovely design that illustrates the power and simplicity of pure CSS. Right at the very top, it uses <c>shape-outside</c> and <c>circle</c> to make text wrap elegantly around a circular shape that contains the navigation. <img src="{att_link}screen_shot_2021-01-31_at_13.08.56.png" href="{att_link}screen_shot_2021-01-31_at_13.08.56.png" align="none" caption="shape-outside in action" scale="25%"> The key piece of CSS is very compact and understandable. <code> shape-outside: circle(21rem at 1.5rem 40%); </code> The page makes liberal use of CSS custom properties (see below) and <c>rem</c> units to make everything scale nicely. It's kind of a master class in CSS and is well worth reading. <h>Background clipping</h> Speaking of clipping, you can assign the <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/background-clip">background-clip</a> property to determine which part of its element a background covers. In particular, setting it to the value <c>text</c> clips the background to show through only for area covered by text. It's been supported for quite some time and allows developers to make dynamic effects that would otherwise have to be hard-coded in graphics. The article <a href="https://www.bram.us/2021/03/15/css-background-clip-demo-text-with-animated-emoji/">CSS <c>background-clip</c> Demo: Text with Animated Emoji</a> shows a neat demo of an animated SVG ghost moving back and forth behind clipped text. <img src="{att_link}image_2021-03-16_221723.png" href="{att_link}image_2021-03-16_221723.png" align="none" caption="background-clip with ghost emoji behind it" scale="40%"> <h>Filters</h> In the same ballpark is the <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter"><c>backdrop-filter</c></a>, which allows you to apply filters to everything behind a particular element. Naturally, you need to make the element at least partially transparent in order to see the effect. <img src="{att_link}screen_shot_2021-03-16_at_22.37.56.png" href="{att_link}screen_shot_2021-03-16_at_22.37.56.png" align="none" caption="backdrop-filter example" scale="50%"> The CSS is very simple and supported on all modern browsers. Being able to create this kind of composition dynamically on the client brings very nice effects without pre-rendered compositing. <h>Clipping and masking</h> <a href="https://www.bram.us/2020/12/28/css-paper-snowflakes/">CSS Paper Snowflakes</a> combines <c>transforms</c>, <c>clip-paths</c>, <c>mask-images</c>, and tons of properties and variables to render what look like pre-built graphics using only CSS (well, SCSS in this case). The article <a href="https://www.bram.us/2021/01/14/css-mix-blend-mode-not-working-set-a-background-color/" source="Bramus">CSS <c>mix-blend-mode</c> not working? Set a <c>background-color</c>!</a> illustrates how to use the <c>mix-blend-mode</c> to make sure that the text has proper contrast versus whichever background it happens to be over. <img src="{att_link}screen_shot_2021-01-16_at_23.09.28.png" href="{att_link}screen_shot_2021-01-16_at_23.09.28.png" align="none" caption="mix-blend-mode: difference in action" scale="50%"> This is a really nice effect and very handy for usability. You can have the browser ensure that text is always readable, regardless of what kind of background slides into place behind it. <h>Sticking & Snapping</h> The article <a href="https://www.bram.us/2020/01/10/smooth-scrolling-sticky-scrollspy-navigation/">Smooth Scrolling Sticky ScrollSpy Navigation</a> provides a tutorial for building a JS-free TOC with sticky headers. The article <a href="https://css-tricks.com/smooth-scrolling-accessibility/" source="CSS Tricks" author="Heather Migliorisi">Smooth Scrolling and Accessibility</a> provides some background, history, and advice on honoring user preferences. The following CSS is enough to get started. The full demo shows how to use a little bit of JS with an <c>IntersectionObserver</c> to implement the ScrollSpy feature in just one line of code. <code> html { scroll-behavior: smooth; } main > nav { position: sticky; top: 2rem; align-self: start; }</code> The article <a href="https://christianheilmann.com/2021/02/09/using-position-sticky-to-create-persistent-headers-in-long-texts/" author="Christian Heilmann">Using position: sticky to create persistent headers in long texts</a> provides a very minimal and highly re-usable example of using this feature for "sticking" headers to the top of the page when scrolling. <code> h1, h2, h3, h4 { position: sticky; top: 0; } </code> And there's also <c>scroll-snap-type</c>, <c>scroll-snap-align</c>, and browser units (e.g. <c>vw</c> and <c>vh</c>) to basically make a slide show out of an HTML file without any JavaScript (<a href="https://codepen.io/bramus/pen/GRJGyGE">demo</a> or another <a href="https://codepen.io/Rik/pen/WNGZodZ">demo</a> with some additional JS to highlight the displayed slide/image in a thumbnail browser). <ul> The article <a href="https://www.bram.us/2020/12/21/sticky-css-grid-items/">Sticky CSS Grid Items</a> is also good (another <a href="https://codepen.io/Rik/pen/bGwoBaR">demo</a> shows an address-book-like implementation) The article <a href="https://calendar.perfplanet.com/2020/html-and-css-techniques-to-reduce-your-javascript/">HTML and CSS techniques to reduce your JavaScript</a> is a multi-step tutorial to make picture browsers with "snap points" and more tricks to control scrolling with minimal or no code. The article <a href="https://css-tricks.com/practical-css-scroll-snapping/" author="Max Kohler" source="CSS-Tricks">Practical CSS Scroll Snapping</a> provides many more examples and techniques. </ul> As for "sticky" or "stuck" elements, <bq>[...] there is one limitation: <b>it is impossible to change the appearance of an element whether it is stuck or not, say with a pseudo-class <c>:stuck</c></b>. This is a general limitation of CSS. In this case, I recommend combining the benefits of position: sticky to keep the element sticking with <c>IntersectionObserver</c> to change its appearance (while taking care not to change its dimensions, to prevent content jumps).</bq> The <a href="https://css-tricks.com/a-table-with-both-a-sticky-header-and-a-sticky-first-column/" source="CSS Tricks" author="Chris Coyier">A table with both a sticky header and a sticky first column</a> provides a good example of using sticky to make frozen columns in tables. For a <i>really</i> fancy scroll-spy, see the <a href="https://lab.hakim.se/progress-nav/">Progress Nav</a> demo. This is very cool-looking, but it's a little bit older, so also check out the <a href="https://www.bram.us/2021/03/20/progress-nav-with-intersectionobserver/" author="Bramus">Progress Nav with IntersectionObserver</a> for a linked version that does the same thing, but uses the <c>IntersectionObserver</c> to reduce the amount of code significantly. <h>Line clamping</h> For limiting text in a box, you can let the browser do all of the heavy lifting by using <c>line-clamp</c> or the even smoother and also standardized <c>webkit-line-clamp</c>. See a <a href="https://codepen.io/Rik/pen/jOMGVGY">demo</a> that shows how to use it in a grid layout. <h>Functions</h> The <c>line-clamp</c> feature is not to be confused with the <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/clamp()"><c>clamp()</c></a> CSS function, which is shorthand for bounding a value between a <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/min()"><c>min()</c></a> and <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/max()"><c>max()</c></a>. There are a <i>ton</i> of <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions">CSS functions</a>, for math, colors, filters, images, fonts, shapes, and more. You can use all of these with variables and custom properties to avoid whole swaths of JavaScript. <h>Grid layouts</h> You'll want to use <c>minmax</c> to override the default minimum size of <c>auto</c>, which is content-sizing, which can get quite large in what the cool kids are calling a <iq>grid blowout</iq>. See <a href="https://www.bram.us/2021/01/28/the-minimum-content-size-in-css-grid/" source="Bramus">The Minimum Content Size In CSS Grid</a> for examples, graphics, and more links and guides. The tutorial <a href="https://www.bram.us/2021/01/23/building-a-side-navigation/">Building a Side Navigation</a> pulls a lot of concepts together to create a common UI element that tends to become a time sink if you don't plan correctly. A lot of the CSS features used in this article help to reduce the work significantly. <h>Table Columns</h> If you've ever wondered what you need <c><col></c> and <c><colgroup></c> for, then <a href="https://www.matuzo.at/blog/highlighting-columns/#table1-heading" author="Manuel Matuzovic">Highlighting columns in HTML tables</a> will show you how to use them to apply styling to a column without much additional markup. He even has an example that styles a "selected" column using the <c>:target</c> pseudo-selector. <h>Images</h> You can also use a simple attribute to tell the browser to be <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attr-loading">proactive about loading images</a>. The article <a href="https://thoughtbot.com/blog/alt-vs-figcaption" source="ThoughtBot" author="Elaina Natario">Alt vs Figcaption</a> nicely illustrates how well browsers now handle the <c>FigCaption</c> tag, which is yet another feature I'd implemented on earthli long ago, but with custom HTML and extra containers and positioning code. It's nice to know that I can replace that all with a single attribute that's been supported for years. <h>Viewport units</h> Viewport units let the developer size elements based on the size of the viewport. This includes not only <c>vw</c> and <c>vh</c>, but also <c>vmin</c> and <c>vmax</c>, which is the minimum or maximum of the two viewport dimensions, respectively. The article <a href="https://css-tricks.com/simple-little-use-case-vmin/" author="Chris Coyier">Simple Little Use Case for <c>vmin</c></a> shows a very simple way to make a highly responsive header without using media queries. <code> header { padding: 10vmin 1rem; } </code> <h>Controls</h> The article <a href="https://www.bram.us/2021/01/13/accept-several-email-addresses-in-a-form-with-the-multiple-attribute/" source="Bramus">Accept several email addresses in a form with the <c>multiple</c> attribute</a> shows you how to use the <c>multiple</c> property to have the browser automatically validate multiple email addresses, all without any custom JavaScript at all. Once you're using HTML validations (and you should), you can use the <c>:invalid</c> pseudo-selector to style elements that need correction. <a href="https://www.bram.us/2021/01/28/form-validation-you-want-notfocusinvalid-not-invalid/" source="Bramus">Form Validation: You want <c>:not(:focus):invalid</c>, not <c>:invalid</c></a> shows several ways of combining it with good UX to avoid annoying users with hyperactive validation messages. A good setup is: <code> .error-message { display: none; } input:not(:focus):invalid { border-color: var(--color-invalid); } input:not(:focus):invalid ~ .error-message { display: block; } input:not(:focus):not(:placeholder-shown):valid { border-color: var(--color-valid); }</code> There's also the new <c>:focus-visible</c> property to help perfect focus-display in forms. <code>/* Hide focus styles if they're not needed, for example, when an element receives focus via the mouse. */ :focus:not(:focus-visible) { outline: 0; } /* Show focus styles on keyboard focus. */ :focus-visible { outline: 3px solid blue; }</code> See <a href="https://www.bram.us/2021/01/28/focus-visible-is-here/" source="Bramus"><c>:focus-visible</c> Is Here</a> for more information. Password controls need a bit more love, as documented in the article <a href="https://www.scottbrady91.com/Authentication/Perfecting-the-Password-Field-with-the-HTML-passwordrules-Attribute" author="Scott Brady">Perfecting the password field with the HTML passwordrules attribute</a>, which makes the case for a new attribute <c>passwordrules</c> to be standardized. His focus is on making password fields maximally accessible and usable for password tools. A weaker---but available---alternative to his proposal is to use the <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/password#htmlattrdefpattern">pattern</a> property to restrict input (helping the user, but not the password generator). To that end, he also mentions that you should set the <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete" source="MDN"><c>autocomplete</c></a>, <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocapitalize" source="MDN"><c> autocapitalize</c></a>, and <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#autocorrect" source="MDN"><c>autocorrect</c></a> (non-standard) properties correctly instead of just leaving them at the defaults. <h>User-resizing</h> The <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/resize" source="MDN">resize</a> CSS property controls the directions in which the user will be able to resize any DOM element. <bq>The <c>resize</c> CSS property sets whether an element is resizable, and if so, in which directions.</bq> <error style="resize: both; width: 200px">This box should be resizable.</error> <h>Accessible Components</h> The article <a href="https://www.smashingmagazine.com/2021/03/complete-guide-accessible-front-end-components/">A Complete Guide To Accessible Front-End Components</a> includes everything from guidance to links to tutorials to full-fledged examples and screenshots of HTML/CSS/JS implementations of commonly used controls that are also accessible. <ul> <a href="http://scottaohara.github.io/accessible_modal_window/">Modals</a> <a href="https://www.sitepoint.com/accessible-footnotes-css/">Footnotes</a> <a href="https://tabpanelwidget.com/">Tabs</a> And <a href="https://www.smashingmagazine.com/2021/03/complete-guide-accessible-front-end-components/">couple of dozen more...</a> </ul> The "Tab Panel" is quite nice in that it responsively switches to an accordion at smaller widths. The article <a href="https://web.dev/building-a-settings-component/" source="web.dev" author="Adam Argyle">Building a Settings component</a> demonstrates accessible components using a lot of pretty advanced---but generally available---techniques, like properties, grids (w/align-items, vw, minmax, auto-fit for pretty much automatic responsiveness with nearly no code), dark/light theming, light JS manipulation of controls, <c>FormData</c>, <c>accent-color</c>, and much more. Watch the <a href="https://www.youtube.com/watch?v=dm7gnp6eh3Q" source="YouTube">embedded video</a> for a very quick, 8-minute overview, play with the <a href="https://www.youtube.com/redirect?event=video_description&redir_token=QUFFLUhqbGg0R3NJQTBnUFp5eS1pVHJJcmwxQzlFWHQ5QXxBQ3Jtc0ttS1NrWV9mQnRhajF2anh0NzZFRFJFZEwxTTIwVEtUY0hmcm9iQ3F5S01kY3FPcFFXT1FTU1pjUEp3b2ZvTFhJVlBKR1NmMVpVNnFOb0U5X1Y2UkJXTm5Ybi1nVjNzTUk3aXlUWXZUVHRKckZjVDQ4aw&q=http%3A%2F%2Fgoo.gle%2F3qysEbW">live demo</a> or grab the <a href="https://github.com/argyleink/gui-challenges/tree/main/settings" source="GitHub">source</a>. <h>Web Components</h> <a href="https://open-wc.org/guides/knowledge/styling/styles-piercing-shadow-dom/#styling-styles-piercing-shadow-dom">Styling: Styles Piercing Shadow DOM</a> shows you how to reset all styles in your component, using the <c>:host</c> pseudo-selector. <code> :host { /* Reset specific CSS properties */ color: initial; /* Reset all CSS properties */ all: initial; } </code> The article <a href="https://nolanlawson.com/2021/01/03/options-for-styling-web-components/" author="Nolan Lawson" source="Read the Tea Leaves">Options for styling web components</a> shows how to design a styling API for a web component using CSS custom properties. <h>Custom Form Elements</h> The article <a href="https://css-tricks.com/creating-custom-form-controls-with-elementinternals/" source="CSS Tricks" author="Caleb Williams">Creating Custom Form Controls with ElementInternals</a> introduces an interesting concept. The example it uses is to make a single "control" that holds several text inputs, which isn't groundbreaking, but it does show the power of packaging CSS/HTML/JS as components that show up as simple tags with properties. None of that is new---we've had web components for a while now---but the <c>ElementInternals</c> allows deep integration into the form's workings, including hooking validation, submitting, drawing, and so on. <h>The <c>inherit</c> value</h> The <c>inherit</c> value is not new, but I often forget to use it as intended. It's meant to help avoid re-stating a base color. The following example changes the color for the <c>nav</c> tags to <c>red</c>, but wants links to retain the original color. <code> body { color: black; } nav { color: red; } nav a { color: black; } </code> Instead of repeating the value <c>black</c>, you can instead use <c>inherit</c>. <code> body { color: black; } nav { color: red; } nav a { color: inherit; } </code> The <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/initial">initial</a> value is also useful. <h><c>content-visibility</c></h> The article <a href="https://www.bram.us/2020/08/10/content-visibility-the-new-css-property-that-boosts-your-rendering-performance/"><c>content-visibility</c>: the new CSS property that boosts your rendering performance</a> discusses a very new feature. It landed in official releases of Chrome, Opera, and Edge in September 2020. <bq>The <c>content-visibility</c> CSS property controls whether or not an element renders its contents at all, along with forcing a strong set of containments, allowing user agents to potentially omit large swathes of layout and rendering work until it becomes needed. Basically it enables the user agent to skip an element's rendering work, including layout and painting, until it is needed, makes the initial page load much faster.</bq> Related to this newer property are the existing <c>will-change</c>, <c>object-fit</c>, and <c>contain</c>. See <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/contain-intrinsic-size" source="MDN">contain-intrinsic-size</a> and <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/content-visibility">content-visibility</a> for more information. <h><c>box-decoration-break</c></h> <info>Update January 2022: Added the section below.</info> The article <a href="https://www.stefanjudis.com/today-i-learned/box-decoration-break-helps-to-define-how-elements-should-be-rendered-across/" author="Stefan Judis" source="">box-decoration-break helps to define how elements should be rendered across lines</a> presents an interesting property that lets you determine how padding, border, and other properties are applied to inline elements that span multiple lines. <img src="{att_link}box-decoration-break.jpg" href="{att_link}box-decoration-break.jpg" align="none" scale="20%"> <h>Isolating Siblings</h> Instead of setting arbitrary z-indexes in your styles, sometimes the <c>isolation</c> property <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/isolation" source="MDN">is a better way of creating a stacking context</a>. <h>Page Visibility</h> The <a href="https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API" source="MDN">Page Visibility API</a> is available in all browsers and provides a high-level API for running code when showing or hiding a page. <bq>With tabbed browsing, there is a reasonable chance that any given webpage is in the background and thus not visible to the user. The Page Visibility API provides events you can watch for to know when a document becomes visible or hidden, as well as features to look at the current visibility state of the page.</bq> Pages can use this to "pause" activity when they're in the background (e.g. server-polling or animations). In the case of animations, though, <iq>Most browsers stop sending <c>requestAnimationFrame()</c> callbacks to background tabs or hidden <c>< iframe></c>s in order to improve performance and battery life.</iq> They also <iq>throttle <c>SetTimeout()</c></iq>. <h>Houdini</h> The <a href="https://developer.mozilla.org/en-US/docs/Web/Houdini" source="MDN">CSS Houdini</a> APIs are a low-level way to hook custom JavaScript into various parts of the rendering pipeline. Of particular interest is the part that's finished and implemented in all browsers: the CSSOM (CSS Object Model) and Houdini, which let a page render custom CSS effects using JavaScript. The collection of low-level APIs is known by the umbrella term <i>Houdini</i>, described in <a href="https://web.dev/houdini-how/">Cross-browser paint worklets and Houdini.how</a>. From the MDN page linked above: <bq>Houdini is a set of low-level APIs that exposes parts of the CSS engine, giving developers the power to extend CSS by hooking into the styling and layout process of a browser’s rendering engine. Houdini is a group of APIs that give developers direct access to the CSS Object Model (CSSOM), enabling developers to write code the browser can parse as CSS, thereby <b>creating new CSS features without waiting for them to be implemented natively in browsers.</b></bq> And: <bq><b>Houdini enables faster parse times than using JavaScript style for style changes.</b> Browsers parse the CSSOM — including layout, paint, and composite processes — before applying any style updates found in scripts. In addition, layout, paint, and composite processes are repeated for JavaScript style updates. Houdini code doesn't wait for that first rendering cycle to be complete. Rather, <b>it is included in that first cycle — creating renderable, understandable styles.</b> Houdini provides an object-based API for working with CSS values in JavaScript.</bq> <a href="https://houdini.how">Houdine.How</a> is a collection of open-source CSS extensions that you can use, extend, and learn from. I heard about this from <a href="https://www.bram.us/2020/12/11/css-houdini-circles-a-houdini-paint-worklet-that-draws-colorful-background-circles/" source="Bram.us" author="Bram Van Damme"><c>css-houdini-circles</c> — A Houdini Paint Worklet that draws Colorful Background Circles</a> (see his <a href="https://github.com/bramus/css-houdini-circles/blob/main/src/index.js" source="GitHub">code</a>) The following video provides an excellent overview in 12 minutes. <media href="https://www.youtube.com/watch?v=5eBar5TI71M" src="https://www.youtube.com/v/5eBar5TI71M" caption="Extending CSS with Houdini" author="Google Chrome Developers" width="560px" source="YouTube"> Once you start making custom effects, you'll run into classic rendering problems, one of which is addressed in the article <a href="https://jakearchibald.com/2020/css-paint-predictably-random/">CSS paint API: Being predictably random</a>, which explains how to use a stable seed to use predictably random data for animation data. While the painting API is relatively well-supported, the <a href="https://www.w3.org/TR/css-layout-api-1/">Layout API</a> is still in early days. <bq>The layout stage of CSS is responsible for generating and positioning fragments from the box tree. [...] This specification describes an API which allows developers to layout a box in response to computed style and box tree changes.</bq> <h>VisBug</h> The <a href="https://chrome.google.com/webstore/detail/visbug/cdockenadnadldjbbgcallicgledbeoc">VisBug Chrome/Opera/Edge Extension</a> is an excellent tool in general, but seems to be indispensable for optimizing Houdini code. <media href="https://www.youtube.com/watch?v=zPHyxvPT0gg?t=1407" src="https://www.youtube.com/v/zPHyxvPT0gg" caption="Day 1 Keynote (Chrome Dev Summit 2018)" source="YouTube" author="Google Chrome Developers" width="560px"> Skip to <b>23:25</b> for the VisBug demonstration. <hr> <info>As of April 2021, the features described below are <i>experimental</i> and either not implemented yet or only available in canary builds or behind feature flags (or both).</info> <h><span id="property_proposals">Advanced Properties</span></h> <a href="https://www.bram.us/2020/12/30/the-future-of-css-higher-level-custom-properties-to-control-multiple-declarations/" author="Bramus Van Damme">The future of CSS: Higher Level Custom Properties to control multiple declarations</a> discusses a very, very recent proposal (December 2020), discussed in detail in the issue <a href="https://github.com/w3c/csswg-drafts/issues/5624" source="GitHub">[css-variables?] Higher level custom properties that control multiple declarations #5624</a> The article <a href="https://web.dev/at-property/" source="web dev" author="Una Kravets">@property: giving superpowers to CSS variables</a> provides more examples. <h>Container Queries</h> Another interesting up-and-coming development is <a href="https://www.bram.us/2020/11/05/container-queries-are-coming-to-chromium/" source="Bram.us">container queries</a>, which are like media queries, but addressing the nearest "root" container in the list of parent containers for the element to which it's applied. The article <a href="https://www.bram.us/2021/03/28/css-container-queries-a-first-look-and-demo/">CSS Container Queries: A First Look + Demo</a> takes you step by step through using it. Basically, you write <c>@container (min-width: 38rem)</c> instead of <c>@media (min-width: 38rem)</c> and assign the <c>contain</c> property, like so: <c>contain: layout inline-size</c>. The article <a href="https://ishadeed.com/article/say-hello-to-css-container-queries/" author="Ahmad Shadeed">Say Hello To CSS Container Queries</a> provides a lot of real-world examples that will make you wonder how we've lived with only viewport-based media queries for so long. <h><span id="nesting">Nesting in CSS</span></h> One of the main features values added by a CSS pre-processor like LESS is nesting, which improves clarity and cuts down on duplicated definitions. The article <a href="https://www.bram.us/2019/03/17/the-future-of-css-nesting-selectors/" author="Bramus">The future of CSS: Nesting Selectors</a> indicates that this feature is coming to mainline CSS, as documented in <a href="https://drafts.csswg.org/css-nesting-1/" source="W3C">CSS Nesting Module</a>. The document is an editors' draft, so there's still quite a way to go. <a href="https://www.bram.us/2021/01/11/nested-media-queries/">Nested Media Queries</a> are already supported, though more as a side-effect of the implementations, not necessarily because it was specified that way. <h>Logical properties</h> The "logical properties" feature will add aliases for some of the venerable CSS properties like <c>margin-right</c> and <c>margin-left</c> that make it easier to build more agnostic and flexible content using, e.g., <c>margin-inline-start</c> and <c>margin-inline-end</c>. Assigning one of these instead of a hard-coded side means that a style will work in both LTR and RTL (for example). The article <a href="https://ishadeed.com/article/css-logical-properties/" author="Ahmad Shadeed">Digging Into CSS Logical Properties</a> provides many more examples. The <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties#reference" source="MDN">full list of proposed properties</a> is quite extensive. Many of the newer modules like flexbox and grid were designed like this from the very start. See also <a href="https://medium.com/swlh/css-logical-properties-are-the-future-of-the-web-i18n-c7d554c6dd72" author="Daniel Yuschick">CSS Logical Properties Are the Future of the Web & I18N</a> for more information and tons of examples, with a demystification of the difference between <c>direction</c> (inline axis, or flow) and <c>writing-mode</c> (block axis). <info><b>Update: 16.10.2021</b> Two more interesting logical properties are <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/inline-size" source="MDN">inline-size</a> and <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/inline-size" source="MDN">block-size</a>, which correspond to <c>width</c> and <c>height</c> in the <c>horizontal-tb</c> <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/writing-mode" source="MDN">writing-mode</a>. Using the logical properties means that the layout works even if the writing mode is changed to <c>vertical-lr</c> or <c>vertical-rl</c>. </info> <h>Portals</h> The article <a href="https://web.dev/hands-on-portals/">Hands-on with Portals: seamless navigation on the web</a> explains how this new feature in Chrome/Chromium improves support for securely embedding content from other sites (i.e. "portals"), as when using OAuth providers. It also generally improves transitions in MPAs (Multiple Page Applications) by allowing one page to prepare another rendered page in memory and then <i>transition</i> to it and perhaps even back. <bq>Single Page Applications (SPAs) offer nice transitions but come at the cost of higher complexity to build. Multi-page Applications (MPAs) are much easier to build, but you end up with blank screens between pages. Portals offer the best of both worlds: the low complexity of an MPA with the seamless transitions of an SPA. Think of them like an <c>< iframe></c> in that they allow for embedding, but unlike an <c>< iframe></c>, they also come with features to navigate to their content.</bq> <h>Page Lifecycle</h> The article <a href="https://developers.google.com/web/updates/2018/07/page-lifecycle-api" source="Google Developers" author="Philip Walton">Page Lifecycle API</a> discusses an improvement over even the "Page Visibility" API (discussed above). Instead just handling visibility, it also provides hooks for suspending and resuming pages. <bq>The Page Lifecycle API, shipping in Chrome 68, provides lifecycle hooks so your pages can safely handle these browser interventions without affecting the user experience. Take a look at the API to see whether you should be implementing these features in your application. [...] While the web platform has long had events that related to lifecycle states — like <c>load</c>, <c>unload</c>, and <c>visibilitychange</c> — these events only allow developers to respond to user-initiated lifecycle state changes.</bq> <ul> The article <a href="https://blog.bitsrc.io/page-lifecycle-api-a-browser-api-every-frontend-developer-should-know-b1c74948bd74" author="Viduni Wickramarachchi" source="Bits and Pieces">Deep Dive into Page Lifecycle API</a> provides some real-world tests and data. Check out the <a href="https://github.com/GoogleChromeLabs/page-lifecycle" source="GitHub">page-lifecycle</a> package for working with the new events. </ul> <hr> <ft>The video <a href="https://www.youtube.com/watch?v=ncYzTvEMCyE"> Thinking on ways to solve CENTERING</a> (and accompanying <a href="https://web.dev/centering-in-css/">article</a>) is an excellent look at several modern techniques for doing centering content, most of them one-liners with good-to-great behavior in many situations.</ft> <ft>While you're at it, take a look at <a href="https://cloudfour.com/thinks/hsl-a-color-format-for-humans/" source="CloudFour" author="Paul Hebert">HSL: a color format for humans</a>, a format that is a <i>lot</i> more intuitive for blending and setting up color schemes than the classic RGB. There are also many guides online for picking a color set, like <a href="https://blog.datawrapper.de/which-color-scale-to-use-in-data-vis/" source="Datawrapper" author="Lisa Charlotte Rost">Which color scale to use when visualizing data</a> and <a href="https://blog.datawrapper.de/beautifulcolors/" source="Datawrapper" author="Lisa Charlotte Rost">How to pick more beautiful colors for your data visualizations</a> as well as tools for choosing colors that work well together, like <a href="https://color.hailpixel.com/#E0B3E6,FAF5F0,A4376A,C8765B,2A547E,A3E0C7,98C757">Colordot</a>, <a href="https://learnui.design/tools/data-color-picker.html#palette">ColorDot</a>, <a href="https://farbvelo.elastiq.ch/">Farbvelo</a>, or <a href="https://medialab.github.io/iwanthue/">I Want Hue</a>.</ft> <ft>If you didn't know about <c>:root</c>, then check out the list of <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements">Pseudo-elements</a> to see which extra parts of a document you have access to with CSS (e.g. the <c>::file-selector-button</c> selector is a relatively new addition that lets you style the button in an upload control).</ft> <ft>The article <a href="https://www.bram.us/2020/12/22/injecting-a-javascript-attack-vector-using-css-custom-properties/" author="Bramus">Injecting a JavaScript Attack Vector using CSS Custom Properties</a> show a site that executes JavaScript stored in a CSS property.</ft>