Tag: Mode

Dark Mode Favicons

Oooo! A bonafide trick from Thomas Steiner. Chrome will soon be supporting SVG favicons (e.g. <link rel="icon" href="/icon.svg">). And you can embed CSS within an SVG with a <style> element. That CSS can use a perfers-color-sceme media query, and as a result, a favicon that supports dark mode!

<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">   <style>     circle {       fill: yellow;       stroke: black;       stroke-width: 3px;     }     @media (prefers-color-scheme: dark) {       circle {         fill: black;         stroke: yellow;       }     }   </style>   <circle cx="50" cy="50" r="47"/> </svg>

Safari also supports SVG, but it’s different…

<link rel="mask-icon" href="/favicon.svg" color="#990000">

You specify the color, so there is no opportunity there for a dark mode situation. A little surprising, since Apple is so all-in on this dark mode stuff. I have no idea if they plan to address that or what.

The post Dark Mode Favicons appeared first on CSS-Tricks.


, ,

“Headless Mode”

A couple of months ago, we invited Marc Anton Dahmen to show off his database-less content management system (CMS) Automad. His post is an interesting inside look at templating engines, including how they work, how CMSs use them, and how they impact the way we write things, such as loops.

Well, Automad just released version 1.3.0 and it introduces a “headless” mode that brings it more in line with where the CMS landscape seems to be headed (pun intended).

And what the heck is a “headless” CMS? I always find that name to be a little weird, but the idea is that the engine for content creation is fully separated from the front-end display and instead stitched together by APIs. This means we’re able to get all the wonderful benefits of creating content in a CMS without being locked into its templating requirements. Chris has a more thorough explanation of the concept from a few years back.

A good example is WordPress and its REST API. We still enjoy the easy UI and extensible administrative features of WordPress, but can send the data anywhere via API to create the front end. Rather write your templates in JavaScript instead of PHP? Go for it!

If the CMS is a body and the front-end view is the head, then the body can unscrew its head and replace it with another. Weird, right?

In any case, whether it’s Automad, WordPress, Sanity, Contentful, Ghost, Netlify CMS, or any others in the growing number of API-first options out there, the move toward headless is a space to watch. HeadlessCMS.org is a good place to do that. We could see vast changes that lead to both better content and developer experiences, which is what all of this is trying to accomplish.

The post “Headless Mode” appeared first on CSS-Tricks.



Weekly Platform News: Internet Explorer Mode, Speed Report in Search Console, Restricting Notification Prompts

In this week’s roundup: Internet Explorer finds its way into Edge, Google Search Console touts a new speed report, and Firefox gives Facebook’s notification the silent treatment.

Let’s get into the news!

Edge browser with new Internet Explorer mode launches in January

Microsoft expects to release the new Chromium-based Edge browser on January 15, on both Windows and macOS. This browser includes a new Internet Explorer mode that allows Edge to automatically and seamlessly render tabs containing specific legacy content (e.g., a company’s intranet) using Internet Explorer’s engine instead of Edge’s standard engine (Blink).

Here’s a sped-up excerpt from Fred Pullen’s presentation that shows the new Internet Explorer mode in action:

(via Kyle Pflug)

Speed report experimentally available in Google Search Console

The new Speed report in Google’s Search Console shows how your website performs for real-world Chrome users (both on mobile and desktop). Pages that “pass a certain threshold of visits” are categorized into fast, moderate, and slow pages.

Tip: After fixing a speed issue, use the “Validate fix” button to notify Google Search. Google will verify the fix and re-index the pages if the issue is resolved.

(via Google Webmasters)

Facebook’s notification prompt will disappear in Firefox

Firefox will soon start blocking notification prompts on websites that request the notification permission immediately on page load (Facebook does this). Instead of the prompt, a small “speech balloon” icon will be shown in the URL bar.

Websites will still be able to show a notification prompt in Firefox as long as they request permission in response to a user interaction (a click, tap, or key press).

(via Marcos Càceres)

More news…

Read more news in my weekly newsletter for web developers. Pledge as little as $ 2 per month to get the latest news from me via email every Monday.

More News →

The post Weekly Platform News: Internet Explorer Mode, Speed Report in Search Console, Restricting Notification Prompts appeared first on CSS-Tricks.


, , , , , , , , , , , ,

A Dark Mode Toggle with React and ThemeProvider

I like when websites have a dark mode option. Dark mode makes web pages easier for me to read and helps my eyes feel more relaxed. Many websites, including YouTube and Twitter, have implemented it already, and we’re starting to see it trickle onto many other sites as well.

In this tutorial, we’re going to build a toggle that allows users to switch between light and dark modes, using a <ThemeProvider wrapper from the styled-components library. We’ll create a useDarkMode custom hook, which supports the prefers-color-scheme media query to set the mode according to the user’s OS color scheme settings.

If that sounds hard, I promise it’s not! Let’s dig in and make it happen.

See the Pen
Day/night mode switch toggle with React and ThemeProvider
by Maks Akymenko (@maximakymenko)
on CodePen.

Let’s set things up

We’ll use create-react-app to initiate a new project:

npx create-react-app my-app cd my-app yarn start

Next, open a separate terminal window and install styled-components:

yarn add styled-components

Next thing to do is create two files. The first is global.js, which will contain our base styling, and the second is theme.js, which will include variables for our dark and light themes:

// theme.js export const lightTheme = {   body: '#E2E2E2',   text: '#363537',   toggleBorder: '#FFF',   gradient: 'linear-gradient(#39598A, #79D7ED)', }  export const darkTheme = {   body: '#363537',   text: '#FAFAFA',   toggleBorder: '#6B8096',   gradient: 'linear-gradient(#091236, #1E215D)', }

Feel free to customize variables any way you want, because this code is used just for demonstration purposes.

// global.js // Source: https://github.com/maximakymenko/react-day-night-toggle-app/blob/master/src/global.js#L23-L41  import { createGlobalStyle } from 'styled-components';  export const GlobalStyles = createGlobalStyle`   *,   *::after,   *::before {     box-sizing: border-box;   }    body {     align-items: center;     background: $ {({ theme }) => theme.body};     color: $ {({ theme }) => theme.text};     display: flex;     flex-direction: column;     justify-content: center;     height: 100vh;     margin: 0;     padding: 0;     font-family: BlinkMacSystemFont, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;     transition: all 0.25s linear;   }

Go to the App.js file. We’re going to delete everything in there and add the layout for our app. Here’s what I did:

import React from 'react'; import { ThemeProvider } from 'styled-components'; import { lightTheme, darkTheme } from './theme'; import { GlobalStyles } from './global';  function App() {   return (     <ThemeProvider theme={lightTheme}>       <>         <GlobalStyles />         <button>Toggle theme</button>         <h1>It's a light theme!</h1>         <footer>         </footer>       </>     </ThemeProvider>   ); }  export default App;

This imports our light and dark themes. The ThemeProvider component also gets imported and is passed the light theme (lightTheme) styles inside. We also import GlobalStyles to tighten everything up in one place.

Here’s roughly what we have so far:

Now, the toggling functionality

There is no magic switching between themes yet, so let’s implement toggling functionality. We are only going to need a couple lines of code to make it work.

First, import the useState hook from react:

// App.js import React, { useState } from 'react';

Next, use the hook to create a local state which will keep track of the current theme and add a function to switch between themes on click:

// App.js const [theme, setTheme] = useState('light');  // The function that toggles between themes const toggleTheme = () => {   // if the theme is not light, then set it to dark   if (theme === 'light') {     setTheme('dark');   // otherwise, it should be light   } else {     setTheme('light');   } }

After that, all that’s left is to pass this function to our button element and conditionally change the theme. Take a look:

// App.js import React, { useState } from 'react'; import { ThemeProvider } from 'styled-components'; import { lightTheme, darkTheme } from './theme'; import { GlobalStyles } from './global';  // The function that toggles between themes function App() {   const [theme, setTheme] = useState('light');   const toggleTheme = () => {     if (theme === 'light') {       setTheme('dark');     } else {       setTheme('light');     }   }      // Return the layout based on the current theme   return (     <ThemeProvider theme={theme === 'light' ? lightTheme : darkTheme}>       <>         <GlobalStyles />         // Pass the toggle functionality to the button         <button onClick={toggleTheme}>Toggle theme</button>         <h1>It's a light theme!</h1>         <footer>         </footer>       </>     </ThemeProvider>   ); }  export default App;

How does it work?

// global.js background: $ {({ theme }) => theme.body}; color: $ {({ theme }) => theme.text}; transition: all 0.25s linear;

Earlier in our GlobalStyles, we assigned background and color properties to values from the theme object, so now, every time we switch the toggle, values change depending on the darkTheme and lightTheme objects that we are passing to ThemeProvider. The transition property allows us to make this change a little more smoothly than working with keyframe animations.

Now we need the toggle component

We’re generally done here because you now know how to create toggling functionality. However, we can always do better, so let’s improve the app by creating a custom Toggle component and make our switch functionality reusable. That’s one of the key benefits to making this in React, right?

We’ll keep everything inside one file for simplicity’s sake,, so let’s create a new one called Toggle.js and add the following:

// Toggle.js import React from 'react' import { func, string } from 'prop-types'; import styled from 'styled-components'; // Import a couple of SVG files we'll use in the design: https://www.flaticon.com import { ReactComponent as MoonIcon } from 'icons/moon.svg'; import { ReactComponent as SunIcon } from 'icons/sun.svg';  const Toggle = ({ theme, toggleTheme }) => {   const isLight = theme === 'light';   return (     <button onClick={toggleTheme} >       <SunIcon />       <MoonIcon />     </button>   ); };  Toggle.propTypes = {   theme: string.isRequired,   toggleTheme: func.isRequired, }  export default Toggle;

You can download icons from here and here. Also, if we want to use icons as components, remember about importing them as React components.

We passed two props inside: the theme will provide the current theme (light or dark) and toggleTheme function will be used to switch between them. Below we created an isLight variable, which will return a boolean value depending on our current theme. We’ll pass it later to our styled component.

We’ve also imported a styled function from styled-components, so let’s use it. Feel free to add this on top your file after the imports or create a dedicated file for that (e.g. Toggle.styled.js) like I have below. Again, this is purely for presentation purposes, so you can style your component as you see fit.

// Toggle.styled.js const ToggleContainer = styled.button`   background: $ {({ theme }) => theme.gradient};   border: 2px solid $ {({ theme }) => theme.toggleBorder};   border-radius: 30px;   cursor: pointer;   display: flex;   font-size: 0.5rem;   justify-content: space-between;   margin: 0 auto;   overflow: hidden;   padding: 0.5rem;   position: relative;   width: 8rem;   height: 4rem;    svg {     height: auto;     width: 2.5rem;     transition: all 0.3s linear;          // sun icon     &:first-child {       transform: $ {({ lightTheme }) => lightTheme ? 'translateY(0)' : 'translateY(100px)'};     }          // moon icon     &:nth-child(2) {       transform: $ {({ lightTheme }) => lightTheme ? 'translateY(-100px)' : 'translateY(0)'};     }   } `;

Importing icons as components allows us to directly change the styles of the SVG icons. We’re checking if the lightTheme is an active one, and if so, we move the appropriate icon out of the visible area — sort of like the moon going away when it’s daytime and vice versa.

Don’t forget to replace the button with the ToggleContainer component in Toggle.js, regardless of whether you’re styling in separate file or directly in Toggle.js. Be sure to pass the isLight variable to it to specify the current theme. I called the prop lightTheme so it would clearly reflect its purpose.

The last thing to do is import our component inside App.js and pass required props to it. Also, to add a bit more interactivity, I’ve passed condition to toggle between “light” and “dark” in the heading when the theme changes:

// App.js <Toggle theme={theme} toggleTheme={toggleTheme} /> <h1>It's a {theme === 'light' ? 'light theme' : 'dark theme'}!</h1>

Don’t forget to credit the flaticon.com authors for the providing the icons.

// App.js <span>Credits:</span> <small><b>Sun</b> icon made by <a href="https://www.flaticon.com/authors/smalllikeart">smalllikeart</a> from <a href="https://www.flaticon.com">www.flaticon.com</a></small> <small><b>Moon</b> icon made by <a href="https://www.freepik.com/home">Freepik</a> from <a href="https://www.flaticon.com">www.flaticon.com</a></small>

Now that’s better:

The useDarkMode hook

While building an application, we should keep in mind that the app must be scalable, meaning, reusable, so we can use in it many places, or even different projects.

That is why it would be great if we move our toggle functionality to a separate place — so, why not to create a dedicated account hook for that?

Let’s create a new file called useDarkMode.js in the project src directory and move our logic into this file with some tweaks:

// useDarkMode.js import { useEffect, useState } from 'react';  export const useDarkMode = () => {   const [theme, setTheme] = useState('light');   const toggleTheme = () => {     if (theme === 'light') {       window.localStorage.setItem('theme', 'dark')       setTheme('dark')     } else {       window.localStorage.setItem('theme', 'light')       setTheme('light')     }   };    useEffect(() => {     const localTheme = window.localStorage.getItem('theme');     localTheme && setTheme(localTheme);   }, []);    return [theme, toggleTheme] };

We’ve added a couple of things here. We want our theme to persist between sessions in the browser, so if someone has chosen a dark theme, that’s what they’ll get on the next visit to the app. That’s a huge UX improvement. For this reasons we use localStorage.

We’ve also implemented the useEffect hook to check on component mounting. If the user has previously selected a theme, we will pass it to our setTheme function. In the end, we will return our theme, which contains the chosen theme and toggleTheme function to switch between modes.

Now, let’s implement the useDarkMode hook. Go into App.js, import the newly created hook, destructure our theme and toggleTheme properties from the hook, and, put them where they belong:

// App.js import React from 'react'; import { ThemeProvider } from 'styled-components'; import { useDarkMode } from './useDarkMode'; import { lightTheme, darkTheme } from './theme'; import { GlobalStyles } from './global'; import Toggle from './components/Toggle';  function App() {   const [theme, toggleTheme] = useDarkMode();   const themeMode = theme === 'light' ? lightTheme : darkTheme;    return (     <ThemeProvider theme={themeMode}>       <>         <GlobalStyles />         <Toggle theme={theme} toggleTheme={toggleTheme} />         <h1>It's a {theme === 'light' ? 'light theme' : 'dark theme'}!</h1>         <footer>           Credits:           <small>Sun icon made by smalllikeart from www.flaticon.com</small>           <small>Moon icon made by Freepik from www.flaticon.com</small>         </footer>       </>     </ThemeProvider>   ); }  export default App;

This almost works almost perfectly, but there is one small thing we can do to make our experience better. Switch to dark theme and reload the page. Do you see that the sun icon loads before the moon icon for a brief moment?

That happens because our useState hook initiates the light theme initially. After that, useEffect runs, checks localStorage and only then sets the theme to dark.

So far, I found two solutions. The first is to check if there is a value in localStorage in our useState:

// useDarkMode.js const [theme, setTheme] = useState(window.localStorage.getItem('theme') || 'light');

However, I am not sure if it’s a good practice to do checks like that inside useState, so let me show you a second solution, that I’m using.

This one will be a bit more complicated. We will create another state and call it componentMounted. Then, inside the useEffect hook, where we check our localTheme, we’ll add an else statement, and if there is no theme in localStorage, we’ll add it. After that, we’ll set setComponentMounted to true. In the end, we add componentMounted to our return statement.

// useDarkMode.js import { useEffect, useState } from 'react';  export const useDarkMode = () => {   const [theme, setTheme] = useState('light');   const [componentMounted, setComponentMounted] = useState(false);   const toggleTheme = () => {     if (theme === 'light') {       window.localStorage.setItem('theme', 'dark');       setTheme('dark');     } else {       window.localStorage.setItem('theme', 'light');       setTheme('light');     }   };    useEffect(() => {     const localTheme = window.localStorage.getItem('theme');     if (localTheme) {       setTheme(localTheme);     } else {       setTheme('light')       window.localStorage.setItem('theme', 'light')     }     setComponentMounted(true);   }, []);      return [theme, toggleTheme, componentMounted] };

You might have noticed that we’ve got some pieces of code that are repeated. We always try to follow the DRY principle while writing the code, and right here we’ve got a chance to use it. We can create a separate function that will set our state and pass theme to the localStorage. I believe, that the best name for it will be setTheme, but we’ve already used it, so let’s call it setMode:

// useDarkMode.js const setMode = mode => {   window.localStorage.setItem('theme', mode)   setTheme(mode) };

With this function in place, we can refactor our useDarkMode.js a little:

// useDarkMode.js import { useEffect, useState } from 'react'; export const useDarkMode = () => {   const [theme, setTheme] = useState('light');   const [componentMounted, setComponentMounted] = useState(false);    const setMode = mode => {     window.localStorage.setItem('theme', mode)     setTheme(mode)   };    const toggleTheme = () => {     if (theme === 'light') {       setMode('dark');     } else {       setMode('light');     }   };    useEffect(() => {     const localTheme = window.localStorage.getItem('theme');     if (localTheme) {       setTheme(localTheme);     } else {       setMode('light');     }     setComponentMounted(true);   }, []);    return [theme, toggleTheme, componentMounted] };

We’ve only changed code a little, but it looks so much better and is easier to read and understand!

Did the component mount?

Getting back to componentMounted property. We will use it to check if our component has mounted because this is what happens in useEffect hook.

If it hasn’t happened yet, we will render an empty div:

// App.js if (!componentMounted) {   return <div /> };

Here is how complete code for the App.js:

// App.js import React from 'react'; import { ThemeProvider } from 'styled-components'; import { useDarkMode } from './useDarkMode'; import { lightTheme, darkTheme } from './theme'; import { GlobalStyles } from './global'; import Toggle from './components/Toggle';  function App() {   const [theme, toggleTheme, componentMounted] = useDarkMode();    const themeMode = theme === 'light' ? lightTheme : darkTheme;    if (!componentMounted) {     return <div />   };    return (     <ThemeProvider theme={themeMode}>       <>         <GlobalStyles />         <Toggle theme={theme} toggleTheme={toggleTheme} />         <h1>It's a {theme === 'light' ? 'light theme' : 'dark theme'}!</h1>         <footer>           <span>Credits:</span>           <small><b>Sun</b> icon made by <a href="https://www.flaticon.com/authors/smalllikeart">smalllikeart</a> from <a href="https://www.flaticon.com">www.flaticon.com</a></small>           <small><b>Moon</b> icon made by <a href="https://www.freepik.com/home">Freepik</a> from <a href="https://www.flaticon.com">www.flaticon.com</a></small>         </footer>       </>     </ThemeProvider>   ); }  export default App;

Using the user’s preferred color scheme

This part is not required, but it will let you achieve even better user experience. This media feature is used to detect if the user has requested the page to use a light or dark color theme based on the settings in their OS. For example, if a user’s default color scheme on a phone or laptop is set to dark, your website will change its color scheme accordingly to it. It’s worth noting that this media query is still a work in progress and is included in the Media Queries Level 5 specification, which is in Editor’s Draft.

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.


Chrome Opera Firefox IE Edge Safari
76 62 67 No 76 12.1

Mobile / Tablet

iOS Safari Opera Mobile Opera Mini Android Android Chrome Android Firefox
13 No No 76 No 68

The implementation is pretty straightforward. Because we’re working with a media query, we need to check if the browser supports it in the useEffect hook and set appropriate theme. To do that, we’ll use window.matchMedia to check if it exists and whether dark mode is supported. We also need to remember about the localTheme because, if it’s available, we don’t want to overwrite it with the dark value unless, of course, the value is set to light.

If all checks are passed, we will set the dark theme.

// useDarkMode.js useEffect(() => { if (   window.matchMedia &&   window.matchMedia('(prefers-color-scheme: dark)').matches &&    !localTheme ) {   setTheme('dark')   } })

As mentioned before, we need to remember about the existence of localTheme — that’s why we need to implement our previous logic where we’ve checked for it.

Here’s what we had from before:

// useDarkMode.js useEffect(() => { const localTheme = window.localStorage.getItem('theme');   if (localTheme) {     setTheme(localTheme);   } else {     setMode('light');   } })

Let’s mix it up. I’ve replaced the if and else statements with ternary operators to make things a little more readable as well:

// useDarkMode.js useEffect(() => { const localTheme = window.localStorage.getItem('theme'); window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches && !localTheme ?   setMode('dark') :   localTheme ?     setTheme(localTheme) :     setMode('light');}) })

Here’s the userDarkMode.js file with the complete code:

// useDarkMode.js import { useEffect, useState } from 'react';  export const useDarkMode = () => {   const [theme, setTheme] = useState('light');   const [componentMounted, setComponentMounted] = useState(false);   const setMode = mode => {     window.localStorage.setItem('theme', mode)     setTheme(mode)   };    const toggleTheme = () => {     if (theme === 'light') {       setMode('dark')     } else {       setMode('light')     }   };    useEffect(() => {     const localTheme = window.localStorage.getItem('theme');     window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches && !localTheme ?       setMode('dark') :       localTheme ?         setTheme(localTheme) :         setMode('light');     setComponentMounted(true);   }, []);    return [theme, toggleTheme, componentMounted] };

Give it a try! It changes the mode, persists the theme in localStorage, and also sets the default theme accordingly to the OS color scheme if it’s available.

Congratulations, my friend! Great job! If you have any questions about implementation, feel free to send me a message!

The post A Dark Mode Toggle with React and ThemeProvider appeared first on CSS-Tricks.


, , , ,

Night Mode with Mix Blend Mode: Difference

Dark mode designs are all the rage right now but here’s an interesting take: Wei Gao has built a night mode on her own site that uses mix-blend-mode: difference to create an effect that looks like this:

Wei explains how she implemented this technique and the edge cases she encountered along the way. I especially love what she had to say about mix-blend-mode functions here:

I remember first playing around with them in Photoshop years ago. Now that browsers are becoming more powerful and we are seeing complex graphical features native to browser rendering. This doesn’t mean we should implement a full photoshop in browsers and nor should we limit our imaginations to just that. Browsers and web pages have their own contexts and goals, as well as a different set of limits. Maybe we should welcome them like new habitants and discover use cases native to this territory.

Indeed! Although Wei’s technique is pretty unique and awesome on its own, this all ties back into the thing that kicked off the whole trend: the prefers-color-scheme media feature that was released in Safari as part of the MacOS 10.4 release that gave us a dark mode preference setting. This is a developing space, so we’re certain to see more innovations and approaches ahead.

Direct Link to ArticlePermalink

The post Night Mode with Mix Blend Mode: Difference appeared first on CSS-Tricks.


, , ,

Weekly Platform News: Mozilla WebThings, Internet Explorer mode, GraphQL

Šime posts regular content for web developers on webplatform.news.

Mozilla WebThings provides complete privacy for user data

Josephine Lau: Smart home companies require that users’ data goes through their servers, which means that people are giving up their privacy for the convenience of a smart home device (e.g., smart light bulb).

We’ve learned that people are concerned about the privacy of their smart home data. And yet, when there’s no alternative, they feel the need to trade away their privacy for convenience.

Mozilla WebThings is an alternative approach to the Internet of Things that stores user data in the user’s home. Devices can be controlled locally via a web interface, and the data is tunneled through a private HTTPS connection.

A diagram showing how Mozilla doesn’t store user data in the cloud, unlike smart home vendors.

An Internet Explorer mode is coming to Edge

Fred Pullen: The next version of Edge will include an Internet Explorer mode for backward compatibility with legacy websites. Edge will also for the first time be available on older versions of Windows (including Windows 7 and 8.1).

By introducing Internet Explorer mode, we’re effectively blurring the lines between the browsers. From an end-user standpoint, it seems like a single browser. … You can use IE mode to limit the sites that instantiate Internet Explorer just to the sites that you approved.

Quick hits: Other interesting articles

Introducing the first Microsoft Edge preview builds for macOS (Microsoft Edge Blog)

Edge Canary (analogous to Chrome Canary) is now officially available on macOS. This version of Edge updates daily.

With our new Chromium foundation, you can expect a consistent rendering experience across the Windows and macOS versions of Microsoft Edge.

#EmberJS2019 More Accessible Than Ever (Yehuda Katz)

Navigating from one page to another in a client-side web app provides no feedback by default in virtually all popular routing solutions across the client-side ecosystem.

Their goal is to make Ember’s router more accessible and screen reader friendly.

Opinion: Five developer trends to watch in 2019 (DeveloperTech)

The article includes a good, short explanation of what GraphQL is and what problems it solves.

Part 2: What the Fr(action)? (CSS IRL)

Read the last section (“Intrinsic and extrinsic sizing”). All three columns have the size 1fr but the middle one is wider because of its content. This can be prevented by using the size minmax(0, 1fr) instead.

Parallel streaming of progressive images (Cloudflare Blog)

Instead of loading from top to bottom, progressive images appear blurry at first and become sharper as more data loads.

The benefits of progressive rendering are unique to JPEG (supported in all browsers) and JPEG 2000 (supported in Safari). GIF and PNG have interlaced modes, but these modes come at a cost of worse compression. WebP doesn’t even support progressive rendering at all. This creates a dilemma: WebP is usually 20%-30% smaller than a JPEG of equivalent quality, but progressive JPEG appears to load 50% faster.

The post Weekly Platform News: Mozilla WebThings, Internet Explorer mode, GraphQL appeared first on CSS-Tricks.


, , , , , , , ,

Reader Mode: The Button to Beat

As a young nerd, I loved to immerse myself in digital worlds, learning the ins and outs of the rules someone else had created for me (intentionally or not). But the older and crankier I get, the more I find myself losing patience when navigating these “delightful” experiences.

This fascination was great for my eventual career as a designer, but unfortunately, it was also like teaching someone kerning—once you learn how to quantify a bad user experience, you can’t go back.

These days, I’m an impatient grump who doesn’t want to take work home. I just want to get in, get what I need, and get out. If there’s any delight I’m experiencing, it’s lost on me because I had such an effortless and annoyance-free time that it simply doesn’t stand out.

One of the features I find myself turning to over and over again is Safari’s Reader Mode. I read a lot of news, and with that comes a lot of bullshit. I now tap the cryptic little icon almost reflexively, confident that I’ll be transported to a land where I can focus on what matters most to me: content.

An iPhone screenshot highlighting the Reader Mode button located in the top-right corner of the screen.

Tapping this button transports me to a land free of newsletter signup modals, surveys, pop-ups, pop-unders, flashing ad banners, automatically-playing video, app install prompts, breaking news alerts, passive-aggressive interstitials, and faux notification permission banners. It slices through the undesirable and unnecessary with ease; the Alexander the Great to the Gordian Knot that is poor user interface design.

Firefox also offers this reading mode. So does Edge. I find myself using it more and more on my laptop with every passing day—especially for reading long-form articles, like this piece. I’d be very surprised to see Chrome institute one natively, as Google is ultimately in the advertising business.

I’m not going to talk about how to best craft your content for Reader Mode. Mandy Michael already covered this in her article, Building websites for Safari Reader Mode and other reading apps. She’s great, and it is a must-read piece.

Building with accessible HTML standards is not a dead-end skill. Far from it. If you spend the effort to craft your experiences with a mind to semantics from the start, your content will be able to adapt to specialized reading modes, as well as whatever the future holds with little to no additional effort. Today’s Reader Mode could be tomorrow’s smart bathroom mirror.

Spending the effort is an important point: Good design isn’t about forcing someone to walk a tightrope across your carefully manicured lawn. Nor is it a puzzle box casually tossed to the user, hoping they’ll unlock it to reveal a hidden treasure. Good design is about doing the hard work to accommodate the different ways people access a solution to an identified problem.

For reading articles, the core problem is turning my ignorance about an issue into understanding (the funding model for this is a whole other complicated concern). The more obstructions you throw in my way to achieve this goal, the more I am inclined to leave and get my understanding elsewhere—all I’ll remember is how poor a time I had while trying to access your content. What is the value of an ad impression if it ultimately leads to that user never returning?

But this isn’t a website about digital media strategy, nor is it one about user conversion. This is a website about CSS and front-end development. What we’re going to discuss is how to keep people like me from hitting that button by relying on this nifty programming language the W3C so wisely gave us. Because if you don’t, all that other stuff—your newsletter signup boxes, your comments, your related articles, your engagement—will be cut away.


What you want to do first is cast a wide net. The more people you can proactively accommodate from the outset, the more people you don’t unintentionally alienate. Our design choices should be invisible—we’re not trying to say, “this is for you.” That should be self-evident. What we’re trying to avoid are scenarios where someone encounters something that communicates, “this is for someone else.”

It’s not too difficult, provided you know what to look out for. Carie Fisher outlines the bulk of it in her brilliant post, Designing Accessible Content: Typography, Font Styling, and Structure.


A basic paragraph style is the wellspring from which all your other type decisions should flow. It’s probably the most common and frequently invoked content type a website has, so it’s important to treat it with the care and respect it deserves. The web is typography, after all.

Heydon Pickering wrote about styling paragraphs way back when in 2011 with his post, The Perfect Paragraph. And here’s the thing: eight years later, this is all still solid advice (sheesh, I’ve been doing this for awhile). When you make design decisions that work with the grain of the web platform, you gain the confidence that you’re creating resilient, robust, and accessible solutions that last.

The neat part about this is that it frees up time to do other things, say reading about gender bias and the undervaluing of HTML and CSS. If anything, do it for me. I am honestly not sure I can handle another case of 2,000 lines of JavaScript used to recreate position: absolute;.



Even though responsive design is nearly a decade old at this point(!), we still seem to ignore a lot of the wisdom Ethan Marcotte so nicely teaches us for free. He’s a smart guy, you should pay attention to what he has to say.

After a complete lack of breakpoints, perhaps the biggest offender I still come across with regards to responsive design is the assumption that a small viewport means teeny-tiny type. Typically, the opposite is true. Small devices are made to be worn or carried, meaning that we move them in physical space to get them into a comfortable reading position. This is the opposite of a larger, more stationary device, such as a monitor, where we move our body to accommodate it instead.

A comfortable reading position means not forcing someone to hold a phone two centimeters away from their face. Ergonomics aren’t likely to change, but devices will. Because of that, you should craft your breakpoint names to be abstract. I personally like names that keep usability in mind, so something along the lines of, “wrist, palm, lap, desk, wall.” It helps keep the user’s circumstance top-of-mind, and moves you away from associating only certain kinds of content as being viable on certain kinds of devices.

These ergonomically-derived designs can be achieved with the help from people like Rachel Andrew, whose in-depth explorations of CSS grid help us understand the power behind a real CSS layout system. Sass experts like Miriam Suzanne then teach us how to use True to codify these layouts and reliably integrate them into our larger Sass systems.

You also want to avoid fallacious device sniffing approaches, or making gross assumptions about a user’s circumstances and capabilities. Just let me increase and decrease that type size. Reader Mode lets me, so I’m going to get there one way or another.


The other thing you need to think about is how that ideal paragraph design actually gets served to a device. A big part of that involves loading our fonts, and ensuring that the loading process prioritizes user experience.


Text downloads quickly; a lot faster than other exotic kinds of content. Browsers will render it gleefully, as it is historically the most important part of the payload. This means that the Reader Mode button is going to show up a lot faster than that distracting auto-playing video of talking heads so thoughtfully jammed into the bottom right-hand corner of my viewport.

And what if we’re on a slow, intermittent, and/or metered connection? Top-of-the-line MacBooks still have to use hotel wifi, just like everyone else.

You want to keep the page from jumping around when our paragraph font loads. This prevents the terrible experience of forcing me to scroll around to rediscover my place as things shift into place. It also helps prevent me from mis-clicking, taking me away from what I want to read because I had the audacity to interact with the page before the bitcoin miners are deployed (thankfully, good people like Laura Kalbag can help us with that one).

The temptation to hit that Reader Mode button is strong, because when I see the main text of the page show up, I know I can easily and reliably avoid all these potential issues.

Helen V. Holmes wrote Type is Your Right!, a beautiful article that effortlessly blends typographic history, capability, and performance. Notably, she discusses how to manage the Flash of Invisible Text (FOIT) and Flash of Unstyled Text (FOUT) to best corral all the aforementioned issues. In response, Monica Dinculescu made Font style matcher, a fantastic tool that lets you bend, stretch, squish, squash, and torture type in ways that would make your stodgy typography professor faint, all in the service of preventing layout jank.


You can (and should) make all sorts of clever optimizations to ensure we’re delivering our images as efficiently as possible. But what happens while I’m waiting for those images to show up? What if they never do?

Since you’re a responsible, inclusive web professional, you’ve already made sure to include alternative text descriptions for our image content. Ire Aderinokun teaches us that you can take that one step further and style broken images. Now even the content that isn’t working as intended looks good. No brittle, overwrought JavaScript here—just good, old fashioned progressive enhancement.

The other type of image you want to consider are icons. There’s lots of reasons to not use icon fonts. Adding one more reason to toss on the pile: icon fonts may not hold up in Reader Mode, as they are constructed using text glyphs. When Reader Mode passes over a page, it may convert the glyph to use the font you specify. This could make for a disastrous experience, especially if the icon is used to communicate critical functionality (e.g. “Press the Home button (☒) to return to the main menu.”).

To avoid this issue, Sara Soueidan teaches us how to convert those icon fonts to SVG . But you know what? She’s so much more than just a SVG expert. She’s an incredible UX developer, and you’d do well to read up on what she’s written. I, for one, have learned a ton.


To help make my reading experience as comfortable as possible, Reader Mode allows me to adjust things like the typeface, the text and background colors, the font size and line height, and the number of words per line. This is great. I’ll frequently toggle back and forth between light and dark backgrounds depending on the time of day.

I also wear glasses, and I know that the older I get, the worst my vision will be. Thanks to Jennifer Aldrich’s writing, I know that this is the norm. After all, we’re all just temporarily abled. I might also need something like Windows High Contrast Mode one day. Thanks to Amelia Bellamy-Royds, I now know how to make my content be the best it can be when viewed in that mode.

The web is flexible. Working on it means getting over your ego and learning to let go. That means accepting that the medium will never be pixel perfect. It means embracing technology like relative units, and more importantly, philosophies like Intrinsic Web Design. That’s brought to us by Jen Simmons, a tireless and passionate advocate for web standards.

I’d love to read your website. I’d love for your harmonious typography to quietly usher me into a flow state, making me forget I was even browsing your site at all.

The post Reader Mode: The Button to Beat appeared first on CSS-Tricks.


, , ,