Web Standards

React Single File Components Are Here

Css Tricks - Tue, 05/12/2020 - 3:56pm

Shawn Wang is talking about RedwoodJS here:

…  it is the first time React components are being expressed in a single file format with explicit conventions.

Which is the RedwoodJS idea of Cells. To me, it feels like a slightly cleaner version of how Apollo wants you to do it with useQuery. Shawn makes that same connection and I know RedwoodJS uses Apollo, so I’m thinking it’s some nice semantic sugar.

There is a lot of cool stuff going on in RedwoodJS. “A highly opinionated stack” if its helpful to think of it that way, but Tom made clear in our last episode of ShopTalk that it’s not like Rails. Not that Rails is bad (it isn’t), but that this new world can do things in new and better ways that make for long-term healthy software.

The post React Single File Components Are Here appeared first on CSS-Tricks.

Using CSS Masks to Create Jagged Edges

Css Tricks - Tue, 05/12/2020 - 10:31am

I was working on a project that had this neat jagged edge along the bottom of a banner image.

Looking sharp… in more ways than one.

It’s something that made me think for a second and I learned something in the process! I thought I’d write up how I approached it so you can use it on your own projects.

I started out with a good old fashioned HTML image in a wrapper element:

<div class="jagged-wrapper">   <img src="path-to-image.jpg" /> </div>

Then I used its ::after pseudo element to drop a repeating background image on it:

.jagged-wrapper::after {   content: "";   background-image: url('data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1 1" preserveAspectRatio="none"><polygon style="fill:white;" points="1,0 1,1 0,1 "/></svg>');   background-size: 30px 30px;   width: 100%;   height: 30px;   position: absolute;   bottom: 0px;   right: 0;   z-index: 2; }

That background image? It’s SVG code converted to a Data URI. Here’s the original SVG code. Chris has a nice video where he walks through that conversion.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1 1" preserveAspectRatio="none">   <polygon style="fill: white;" points="1,0 1,1 0,1 "/> </svg>

“There we go!” I thought.

CodePen Embed Fallback

While that certainly works, geez, that’s a lot of hassle. It’s difficult to read SVG markup in CSS like that. Plus, it’s annoying to have to remember to quote them (e.g. url('data:image/svg+xml'...)). Sure, we can base64 encode the SVG to avoid that, but that’s even more annoying. Plus, the SVG needs to be filled with the same background color as the image (or wherever it is used), or else it won’t work.

Wait, isn’t this what masking is for? Yes! Yes, this is what masking is for.

That led me to a new approach: use an image like the one above as a CSS mask so that the “missing” bits of the banner image would actually be missing. Rather than drawing triangles of the background color on top of the banner, we should instead mask away those triangles from the banner entirely and let the real background show through. That way, it works on any background!

Masking is pretty much supported everywhere — at least in the simple way I’m talking about here. We’re also talking about something that can be implemented with progressive enhancement; if masks aren’t supported in a given browser, then you just don’t get the sawtooth effect. Definitely not the end of the world.

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

DesktopChromeFirefoxIEEdgeSafari85*53No81*TP*Mobile / TabletAndroid ChromeAndroid FirefoxAndroidiOS Safari81*6881*13.4*

One way a CSS mask works is to provide an image with an alpha channel as a mask-image. The underlying element — the one that’s being masked — becomes (semi-)transparent to the degree that the alpha channel of the mask-image dictates. So if your mask image is a white teapot on a transparent background, then the masked element will be cut to the shape of the teapot and everything outside that will be hidden.

CodePen Embed Fallback

Masking can be a tricky concept to grok. Sarah Drasner has an article that takes a deep-dive on masking, including how it is different from clipping. There’s much more that masks can do than what we’re covering here. Check the specs, caniuse, and MDN for even more information.

What we need is a single “sawtooth”-like image similar to the SVG above, where the top-left half is filled white and the bottom-left is left semi-transparent. And, ideally that image wouldn’t be an actual SVG, since that would land us back into the ugly data URI mess we were in before.

At this point you might be thinking: “Hey, just embed the SVG in the CSS directly, define a mask in it, then point the CSS at the mask ID in the SVG!”

Nice idea! And it’s certainly doable, if you can edit the HTML. For my specific project, however, I was working in WordPress and I really wanted to confine my changes to pure CSS rather than injecting extra parts into the HTML. That would have been a lot more work. I don’t think this is uncommon; for a presentational change like this, not having to edit the HTML is useful. We’re mostly on board with the idea of avoiding semantically worthless wrapper elements just to provide styling hooks, but I feel that also applies to adding entire SVG markup to the document… or even a WordPress template.

We can use a CSS linear gradient to create a triangle shape instead:

.el {   linear-gradient(     to bottom right,     white,     white 50%,     transparent 50%,     transparent   ); }

Here that is on a radial background, so you can see it’s really transparent:

CodePen Embed Fallback

Great! We can just use that as a mask-image on our banner, right? We need to set mask-size, which is like background-size, and mask-repeat, like background-repeat, and we’re good?

CodePen Embed Fallback

Unfortunately, no. Not so good.

The first reason is that, unless you’re using Firefox, you’ll likely see no masking at all on that example above. This is because Blink and WebKit still only support masking with a vendor prefix at the time of writing. That means we need -webkit- prefixed versions of everything.

CodePen Embed Fallback

Vendor prefixing aside, what we’re doing is also conceptually wrong. If we confine the mask to just the bottom stripe of the image with mask-size, then the rest of the image has no mask-image at all, which masks it out entirely. As a result, we can’t use the sawtooth alone as a mask. What we need is a mask-image that is a rectangle the size of the image with just a sawtooth at the bottom. 

Something like this:

CodePen Embed Fallback

We do that with two gradient images. The first image is the same sawtooth triangle as above, which is set to repeat-x and positioned at the bottom so that it repeats only along the bottom edge of the image. The second image is another gradient that is transparent for the bottom 30px (so as to not interfere with the sawtooth), opaque above that (which is shown going from black to white in the demo), and takes up the whole size of the element. 

So we now have this wedge-shaped piece, with a single triangle sawtooth at the bottom, and it occupies the entire height of our banner image in two separate pieces. Finally, we can use these pieces with mask-image by repeating them horizontally across our image, and it should have the effect we want:

CodePen Embed Fallback

And there we have it!

The post Using CSS Masks to Create Jagged Edges appeared first on CSS-Tricks.

Why does writing matter in remote work?

Css Tricks - Tue, 05/12/2020 - 7:24am

Talk to anyone who has an active blog and I bet they’ll tell you it’s been valuable to them. Maybe it’s opened doors. Maybe it’s got them a job. Maybe it’s got them a conference invite. Maybe they just like the thrill of knowing people have read and responded to it. Maybe they learned a lot through its creation and maintenance.

Khoi Vinh said:

It’s hard to overstate how important my blog has been, but if I were to try to distill it down into one word, it would be: “amplifier.”

But what about other kinds of writing? Just day to day writing? Is that important for web workers? “Especially now”?

Tim Casasola:

In remote work, we communicate primarily through writing. We send messages in Slack. We document projects in Notion. We send meeting invites with a written description of the purpose. We’re writing all the time.

It’s just so damn important for team work of any kind, particularly when you aren’t next to each other physically.

While writing forces people to think clearly, writing also forces teams to think clearly. In my experience, having a clearly written thing makes it easy for folks to collaborate with me. This is because people naturally enjoy poking holes in arguments, adding points that were missed, or mentioning any risks that weren’t taken into account. I’ve found it helpful to use this human tendency to my advantage. Extra opinions and poked holes are hard to surface if you didn’t write something in the first place.

Direct Link to ArticlePermalink

The post Why does writing matter in remote work? appeared first on CSS-Tricks.

Accepting Payments (including Recurring Payments) on WordPress.com

Css Tricks - Tue, 05/12/2020 - 6:49am

I’m a fan of building websites with the least amount of technical debt and things you have to be responsible for as possible for what you wanna do. Sometimes you take on this debt on purpose because you have to, but when you don’t, please don’t ;).

Let’s say you need to build a site that can take money from customers, but on a recurring basis. WordPress.com can do that now, and it’s a fantastic choice because it’s all of the power and control and none of the debt.

Here’s my thinking…

1) WordPress.com is the fastest way to spin up a WordPress site.

Not only is it fast, but you don’t have to worry about anything. Servers, SSL, security, performance, accessibility… that’s all handled for you and you can focus on what you do best. Even if you’re a seasoned developer, I’m sure you can understand how this is compelling. Automating work is what the best developers do.

2) WordPress.com sites can be eCommerce sites.

Not only sell-a-product style sites, but also recurring payments sites. Meaning you can very easily set up a subscription service, membership site, or site for monthly donations.

The pricing is like this:

WordPress.com PlanJetpack planRelated FeesWordPress.com eCommerce —NoneWordPress.com BusinessJetpack Professional2%WordPress.com PremiumJetpack Premium4%WordPress.com PersonalJetpack Personal 8%

So you do the math and figure out the most economical plan for you. That eCommerce plan on WordPress.com is only $45/month and means zero additional fees, so I imagine once you’re up and running and making sales, that plan becomes the obvious choice.

Ideas!
  • You build custom weekly meal plans for families and charge monthly for that.
  • You have a membership site for physical training videos where people have to be a member to see the videos.
  • Your site is has a bunch of completely free great content, and you offer a way to give yearly donations to support it.

Why roll your own eCommerce when you don’t have to?

3) It used to be that your WordPress site was a bit limited on WordPress.com, but those days are over.

eCommerce is one aspect of that, but I’m talking full SFTP and database access. You can build custom themes, use your own plugins, just like any other WordPress site. So if you’re thinking that you’re giving up too much control by going with WordPress.com, make sure to re-evaluate that.

So knowing all that, I’d say you really should give WordPress.com a hard look when you’re about to spin up an eCommerce site. I’ve seen far too much over-engineering and mountains of technical debt in my life, I’d rather see people use simpler tools and get started doing their actual business, especially to start.

The post Accepting Payments (including Recurring Payments) on WordPress.com appeared first on CSS-Tricks.

Dealing With Stale Props and States in React’s Functional Components

Css Tricks - Tue, 05/12/2020 - 4:56am

There’s one aspect of JavaScript that always has me pulling my hair: closures. I work with React a lot, and the overlap there is that they can sometimes be the cause of stale props and state. We’ll get into exactly what that means, but the trouble is that the data we use to build our UI can be totally wrong in unexpected ways, which is, you know, bad.

Stale props and states

Long story short: it’s when code that is executed asynchronously has a reference to a prop or state that is no longer fresh, and thus, the value it returns is not the latest one.

To be even more clear, let’s play around with the same stale reference example React has in its documentation.

function Counter() {   const [count, setCount] = useState(0);   function handleAlertClick() {     setTimeout(() => {       alert("You clicked on: " + count);     }, 3000);   }   return (     <div>       <p>You clicked {count} times</p>       <button onClick={() => setCount(count + 1)}>Click me</button>       <button onClick={handleAlertClick}>Show alert</button>     </div>   ); }

(Live demo)

Nothing fancy here. We have a functional component named Counter. It keeps track of how many times the user has clicked one button and shows an alert that displays how many times that button was clicked when clicking another button. Try this:

  1. Click the “Click me” button. You are going to see the click counter go up.
  2. Now click the “Show alert”button. Three seconds should go by and then trigger an alert telling you how many times you clicked the “Click me” button.
  3. Now, click the “Show alert” button again and quickly click the “Click me” button before it triggers the alert in three seconds.

See what happens? The count shown on the page and the count shown in the alert do not match. The number in the alert is not just some random number, though. That number is the value the count variable had in the moment the asynchronous function inside the setTimeout was defined, which is the moment the “Show alert” button is clicked.

That’s just how closures work. We’re not going to get into the specifics of them in this post, but here are some docs that cover them in greater detail.

Let’s focus on how we can avoid these stale references with our states and props.

React offers a tip on how to deal with stale dates and props in the same documentation where the example was pulled.

If you intentionally want to read the latest state from some asynchronous callback, you could keep it in a ref, mutate it, and read from it.

By keeping the value  asynchronously in a ref, we can bypass stale references. If you need to know more about ref in functional components, React’s documentation has a lot more information.

So, that begs the question: How can we keep our props or state in a ref?

Let’s do it the dirty way first.

The dirty way to store props and state in a ref

We can easily create a ref using useRef() and use count as its initial value. Then, wherever the state is being updated, we set the ref.current property to the new value. Lastly, use ref.current instead of count in the asynchronous part of our code.

function Counter() {   const [count, setCount] = useState(0);   const ref = useRef(count); // Make a ref and give it the count   function handleAlertClick() {     setTimeout(() => {       alert("You clicked on: " + ref.current); // Use ref instead of count     }, 3000);   }   return (     <div>       <p>You clicked {count} times</p>       <button         onClick={() => {           setCount(count + 1);           ref.current = count + 1; // Update ref whenever the count changes         }}       >         Click me       </button>       <button         onClick={() => {           handleAlertClick();         }}       >         Show alert       </button>     </div>   ); }

(Live demo)

Go ahead and do the same as last time. Click “Show alert” and then click “Click me” before the alert is triggered in three seconds.

Now we have the latest value!

Here’s why it works. When the asynchronous callback function is defined inside setTimeout, it saves a reference to the variables it uses, which is count in this case. This way, when the state updates, React not only changes the value but the variable reference in memory is completely different as well.

This means that — even if the state’s value is non-primitive — the variable you are working with in your asynchronous callback is not the same in memory. An object that would typically keep its reference throughout different functions now has a different value.

How does using a ref solve this? If we take a quick look at React’s docs again, we find an interesting, but easy-to-miss, bit of information:

[…] useRef will give you the same ref object on every render.

It doesn’t matter what we do. Throughout the lifetime of your component, React will give us the exact same ref object in memory. Any callback, no matter when it’s defined or executed, is working with the same object. No more stale reference.

The cleaner way to store props and state in a ref

Let’s be honest… using a ref like that is an ugly fix. What happens if your state is being updated in a thousand different places? Now you have to change your code and manually update the ref in all those places. That’s a no-no.

We are going to make this more scalable by giving ref the value of the state automatically when the state changes.

Let’s start by getting rid of the manual change to the ref in the “Click me”button.

Next, we make a function called updateState that is called whenever we need to change the state. This function takes the new state as an argument and it sets the ref.current property to the new state and updates the state as well with that same value.

Finally, let’s substitute the original setCount function React gives us with the new updateState function where the state is being updated.

function Counter() {   const [count, setCount] = useState(0);   const ref = useRef(count);   // Keeps the state and ref equal   function updateState(newState) {     ref.current = newState;     setCount(newState);   }   function handleAlertClick() { ... }   return (     <div>       <p>You clicked {count} times</p>       <button         onClick={() => {           // Use the created function instead of the manual update           updateState(count + 1);         }}       >         Click me       </button>       <button onClick={handleAlertClick}>Show alert</button>     </div>   ); }

(Live demo)

Using a custom hook

The cleaner solution works just fine. It gets the job done just like the dirty solution, but only calls a single function to update the state and ref.

But guess what? We can do better. What if we need to add more states? What if we want to do this in other components too? Let’s take the state, ref and updateState function and make them truly portable. Custom hooks to the rescue!

Outside the Counter component, we are going to define a new function. Let’s name it useAsyncReference. (It can be named anything, really, but note that it’s common practice to name custom hooks with “use” as a prefix.) Our new hook will have a single parameter for now. We’ll call it value.

Our previous solution had the same information stored twice: once in the state and once in the ref. We are going to optimize that by keeping the value just in ref this time. In other words, we will create a ref and give it the value parameter as its initial value.

Right after the ref, we will make an updateState function that takes the new state and sets it to the ref.current property.

Lastly, we return an array with ref and the updateState function, very similar to what React does with useState.

function useAsyncReference(value) { const ref = useRef(value); function updateState(newState) { ref.current = newState; } return [ref, updateState]; } function Counter() { ... }

We are forgetting something! If we check the useRef documentation, we learn that updating a ref does not trigger a re-render. So, while ref has the updated value, we wouldn’t see the changes on screen. We need to force a re-render every time ref gets updated.

What we need is a fake state. The value doesn’t matter. It’s only going to be there to provoke the re-render. We can even ignore the state and only keep its update function. We are calling that update function forceRender and giving it an initial value of false.

Now, inside updateState, we force the re-render by calling forceRender and passing it a state different to the current one after setting ref.current to newState.

function useAsyncReference(value) {   const ref = useRef(value);   const [, forceRender] = useState(false);   function updateState(newState) {     ref.current = newState;     forceRender(s => !s);   }   return [ref, updateState]; } function Counter() { ... }

Take whatever value it has and return the opposite. The state doesn’t really matter. We are merely changing it so React detects a change in state and re-renders the component.

Next, we can clean the Count component and remove the previously used useState, ref and updateState function, then implement the new hook. The first value of the returned array is the state in the form of a ref. We’ll keep calling it count, where the second value is the function to update the state/ref. We’ll continue calling it setCount.

We also have to change the references to the count since now that they all must be count.current. And we must call setCount instead of calling updateState.

function useAsyncReference(value) { ... } function Counter() {   const [count, setCount] = useAsyncReference(0);   function handleAlertClick() {     setTimeout(() => {       alert("You clicked on: " + count.current);     }, 3000);   }   return (     <div>       <p>You clicked {count.current} times</p>       <button         onClick={() => {           setCount(count.current + 1);         }}       >         Click me       </button>       <button onClick={handleAlertClick}>Show alert</button>     </div>   ); } Making this work with props

We have a truly portable solution for our problem. But guess what… there’s still a little more to do. Specifically, we need to make the solution compatible with props.

Let’s take the “Show alert” button and handleAlertClick function to a new component outside the Counter component. We are gonna call it Alert and it’s going to take a single prop called count. This new component is going to show the count prop value we are passing it in an alert after a three second delay.

function useAsyncReference(value) { ... } function Alert({ count }) {   function handleAlertClick() {     setTimeout(() => {       alert("You clicked on: " + count);     }, 3000);   }   return <button onClick={handleAlertClick}>Show alert</button>; } function Counter() { ... }

In Counter, we’re swapping the “Show alert” button for the Alert component. We’ll pass count.current to the count prop.

function useAsyncReference(value) { ... } function Alert({ count }) { ... } function Counter() {   const [count, setCount] = useAsyncReference(0);   return (     <div>       <p>You clicked {count.current} times</p>       <button         onClick={() => {           setCount(count.current + 1);         }}       >         Click me       </button>       <Alert count={count.current} />     </div>   ); }

(Live demo)

Alright, time to run through the testing steps again. See? Even though we are using a safe reference to the count in Counter, the reference to the count prop in the Alert component is not asynchronously safe and our custom hook is not suitable to use with props… yet.

Lucky for us, the solution is fairly simple.

All we have to do is add a second parameter to our useAsyncReference hook named isProp, with false as the initial value. Just before we return the array with ref and updateState, we set up a condition. If isProp is true, we set the ref.current property to value and only return ref.

function useAsyncReference(value, isProp = false) {   const ref = useRef(value);   const [, forceRender] = useState(false);   function updateState(newState) {     ref.current = newState;     forceRender(s => !s);   }   if (isProp) {     ref.current = value;     return ref;   }   return [ref, updateState]; } function Alert({ count }) { ... } function Counter() { ... }

Now let’s update Alert so that is uses the hook. Remember to pass true as a second argument to useAsyncReference since we are passing a prop and not a state.

function useAsyncReference(value) { ... } function Alert({ count }) {   const asyncCount = useAsyncReference(count, true);   function handleAlertClick() {     setTimeout(() => {       alert("You clicked on: " + asyncCount.current);     }, 3000);   }   return <button onClick={handleAlertClick}>Show alert</button>; } function Counter() { ... }

(Live demo)

Give it another try. Now it works perfectly whether you use states or props.

One last thing…

There’s one last change I’d like to make. React’s useState docs tell us that React will bail out of a re-render if the new state is identical to the previous one. Our solution doesn’t do that. If we pass the current state again to the hook’s updateState function, we will force a re-render no matter what. Let’s change that.

Let’s put the body of updateState inside an if statement and execute it when ref.current is different than the new state. The comparison must be done with Object.is(), just like React does.

function useAsyncReference(value, isProp = false) {   const ref = useRef(value);   const [, forceRender] = useState(false);   function updateState(newState) {     if (!Object.is(ref.current, newState)) {       ref.current = newState;       forceRender(s => !s);     }   }   if (isProp) {     ref.current = value;     return ref;   }   return [ref, updateState]; } function Alert({ count }) { ... } function Counter() { ... }

Now we are finally done!

React can sometimes seem like a black box that is full of little quirks. Those quirks might be daunting to deal with, like the one we just tackled. But if you are patient and enjoy being challenged, you’ll soon realize it’s an awesome framework and a pleasure to work with.

The post Dealing With Stale Props and States in React’s Functional Components appeared first on CSS-Tricks.

How I Put the Scroll Percentage in the Browser Title Bar

Css Tricks - Tue, 05/12/2020 - 4:54am

Some nice trickery from Knut Melvær.

Ultimately the trick boils down to figuring out how far you’ve scrolled on the page and changing the title to show it, like:

document.title = `${percent}% ${post.title}`

Knut’s trick assumes React and installing an additional library. I’m sure that library does all kinds of smart stuff, but if you’re looking to do this “vanilla” style, I’d probably rock something like this…

const percentLabel = document.querySelector("#percent"); const originalTitle = document.title; window.addEventListener("scroll", () => { let scrollTop = window.scrollY; let docHeight = document.body.offsetHeight; let winHeight = window.innerHeight; let scrollPercent = scrollTop / (docHeight - winHeight); let scrollPercentRounded = Math.round(scrollPercent * 100); percentLabel.innerHTML = scrollPercentRounded; document.title = `(${scrollPercentRounded}%) ${originalTitle}`; });

Here’s a project, and here’s the deployed site so you can see it in action.

Direct Link to ArticlePermalink

The post How I Put the Scroll Percentage in the Browser Title Bar appeared first on CSS-Tricks.

CSS Animation Timelines: Building a Rube Goldberg Machine

Css Tricks - Mon, 05/11/2020 - 1:34pm

If you’re going to build a multi-step CSS animation or transition, you have a particular conundrum. The second step needs a delay that is equal to the duration of the first step. And the third step is equal to the duration of the first two steps, plus any delay in between. It gets more and more complicated until you might just be like, nahhhhh I’ll use more technology to help me.

Paul Hebert:

Lately I’ve been using custom properties to plan out pure CSS timelines for complex animations.

Cool. And it can get completely nuts.

Direct Link to ArticlePermalink

The post CSS Animation Timelines: Building a Rube Goldberg Machine appeared first on CSS-Tricks.

min(), max(), and clamp() are CSS magic!

Css Tricks - Mon, 05/11/2020 - 1:34pm

Nice video from Kevin Powell. Here are some notes, thoughts, and stuff I learned while watching it. Right when they came out, I was mostly obsessed with font-size usage, but they are just functions, so they can be used anywhere you’d use a number, like a length.

Sometimes pretty basic usage allows for tighter code, but the change to get there feels a little mind-bending. Like how to set a “max” here, you really use min().

.el { width: 75%; max-width: 600px; /* tighter, but the change from max to min feels weird */ width: min(75%, 600px); }

The min() and max() functions can take more than two values, which is cool, but hard to keep straight what is going on! It would be nice if DevTools could tell you which one it picked at any given time.

.el { width: min(100px, 25%, 50vh, 30ch); }

You don’t need a calc() to do math inside!

.el { width: min(10vw + 10%, 100px); }

It’s reasonable you’d want to be setting a min and max value. You can nest the functions to do this, but it’s less mind-bendy to do with clamp().

.el { /* Note we're always using a relative unit somewhere so that zooming stays effective. */ font-size: clamp(0.9rem, 1vw + 1rem, 2.2rem); }

Here’s the video embedded:

Direct Link to ArticlePermalink

The post min(), max(), and clamp() are CSS magic! appeared first on CSS-Tricks.

Turning a Fixed-Size Object into a Responsive Element

Css Tricks - Mon, 05/11/2020 - 4:46am

I was in a situation recently where I wanted to show an iPhone on a website. I wanted users to be able to interact with an application demo on this “mock” phone, so it had to be rendered in CSS, not an image. I found a great library called marvelapp/devices.css. The library implemented the device I needed with pure CSS, and they looked great, but there was a problem: the devices it offered were not responsive (i.e. they couldn’t be scaled). An open issue listed a few options, but each had browser incompatibilities or other issues. I set out to modify the library to make the devices responsive.

Here is the final resizable library. Below, we’ll walk through the code involved in creating it.

The original library was written in Sass and implements the devices using elements with fixed sizing in pixels. The authors also provided a straightforward HTML example for each device, including the iPhone X we’ll be working with throughout this article. Here’s a look at the original. Note that the device it renders, while detailed, is rather large and does not change sizes.

CodePen Embed Fallback Here’s the approach

There are three CSS tricks that I used to make the devices resizable:

  1. calc(), a CSS function that can perform calculations, even when inputs have different units
  2. --size-divisor, a CSS custom property used with the var() function
  3. @media queries separated by min-width

Let’s take a look at each of them.

calc()

The CSS calc() function allows us to change the size of the various aspects of the device. The function takes an expression as an input and returns the evaluation of the function as the output, with appropriate units. If we wanted to make the devices half of their original size, we would need to divide every pixel measurement by 2.

Before:

width: 375px;

After:

width: calc(375px / 2);

The second snippet yields a length half the size of the first snippet. Every pixel measurement in the original library will need to be wrapped in a calc() function for this to resize the whole device.

var(–size-divisor)

A CSS variable must first be declared at the beginning of the file before it can be used anywhere.

:root {   --size-divisor: 3; }

With that, this value is accessible throughout the stylesheet with the var() function. This will be exceedingly useful as we will want all pixel counts to be divided by the same number when resizing devices, while avoiding magic numbers and simplifying the code needed to make the devices responsive.

width: calc(375px / var(--size-divisor));

With the value defined above, this would return the original width divided by three, in pixels.

@media

To make the devices responsive, they must respond to changes in screen size. We achieve this using media queries. These queries watch the width of the screen and fire if the screen size crosses given thresholds. I chose the breakpoints based on Bootstrap’s sizes for xs, sm, and so on

There is no need to set a breakpoint at a minimum width of zero pixels; instead, the :root declaration at the beginning of the file handles these extra-small screens. These media queries must go at the end of the document and be arranged in ascending order of min-width.

@media (min-width: 576px) {   :root {     --size-divisor: 2;   } } @media (min-width: 768px) {   :root {     --size-divisor: 1.5;   } } @media (min-width: 992px) {    :root {     --size-divisor: 1;   } } @media (min-width: 1200px) {    :root {     --size-divisor: .67;   } }

Changing the values in these queries will adjust the magnitude of resizing that the device undergoes. Note that calc() handles floats just as well as integers.

Preprocessing the preprocessor with Python

With these tools in hand, I needed a way to apply my new approach to the multi-thousand-line library. The resulting file will start with a variable declaration, include the entire library with each pixel measurement wrapped in a calc() function, and end with the above media queries.

Rather than prepare the changes by hand, I created a Python script that automatically converts all of the pixel measurements.

def scale(token):   if token[-2:] == ';\n':     return 'calc(' + token[:-2] + ' / var(--size-divisor));\n'   elif token[-3:] == ');\n':     return '(' + token[:-3] + ' / var(--size-divisor));\n'   return 'calc(' + token + ' / var(--size-divisor))'

This function, given a string containing NNpx, returns calc(NNpx / var(--size-divisor));. Throughout the file, there are fortunately only three matches for pixels: NNpx, NNpx; and NNpx);. The rest is just string concatenation. However, these tokens have already been generated by separating each line by space characters.

def build_file(scss):   out = ':root {\n\t--size-divisor: 3;\n}\n\n'   for line in scss:     tokens = line.split(' ')     for i in range(len(tokens)):       if 'px' in tokens[i]:         tokens[i] = scale(tokens[i])     out += ' '.join(tokens)   out += "@media (min-width: 576px) {\n  \     :root {\n\t--size-divisor: 2;\n  \     }\n}\n\n@media (min-width: 768px) {\n \     :root {\n\t--size-divisor: 1.5;\n  \     }\n}\n\n@media (min-width: 992px) { \     \n  :root {\n\t--size-divisor: 1;\n  \     }\n}\n\n@media (min-width: 1200px) { \     \n  :root {\n\t--size-divisor: .67;\n  }\n}"   return out

This function, which builds the new library, begins by declaring the CSS variable. Then, it iterates through the entire old library in search of pixel measurements to scale. For each of the hundreds of tokens it finds that contain px, it scales that token. As the iteration progresses, the function preserves the original line structure by rejoining the tokens. Finally, it appends the necessary media queries and returns the entire library as a string. A bit of code to run the functions and read and write from files finishes the job.

if __name__ == '__main__':   f = open('devices_old.scss', 'r')   scss = f.readlines()   f.close()   out = build_file(scss)   f = open('devices_new.scss', 'w')   f.write(out)   f.close()

This process creates a new library in Sass. To create the CSS file for final use, run:

sass devices_new.scss devices.css

This new library offers the same devices, but they are responsive! Here it is:

CodePen Embed Fallback

To read the actual output file, which is thousands of lines, check it out on GitHub.

Other approaches

While the results of this process are pretty compelling, it was a bit of work to get them. Why didn’t I take a simpler approach? Here are three more approaches with their advantages and drawbacks.

zoom

One initially promising approach would be to use zoom to scale the devices. This would uniformly scale the device and could be paired with media queries as with my solution, but would function without the troublesome calc() and variable.

This won’t work for a simple reason: zoom is a non-standard property. Among other limitations, it is not supported in Firefox.

Replace px with em

Another find-and-replace approach prescribes replacing all instances of px with em. Then, the devices shrink and grow according to font size. However, getting them small enough to fit on a mobile display may require minuscule font sizes, smaller than the minimum sizes browsers, like Chrome, enforce. This approach could also run into trouble if a visitor to your website is using assistive technology that increases font size.

This could be addressed by scaling all of the values down by a factor of 100 and then applying standard font sizes. However, that requires just as much preprocessing as this article’s approach, and I think it is more elegant to perform these calculations directly rather than manipulate font sizes.

scale()

The scale() function can change the size of entire objects. The function returns a <transform-function>, which can be given to a transform attribute in a style. Overall, this is a strong approach, but does not change the actual measurement of the CSS device. I prefer my approach, especially when working with complex UI elements rendered on the device’s “screen.”

Chris Coyier prepared an example using this approach.

CodePen Embed Fallback In conclusion

Hundreds of calc() calls might not be the first tool I would reach for if implementing this library from scratch, but overall, this is an effective approach for making existing libraries resizable. Adding variables and media queries makes the objects responsive. Should the underlying library be updated, the Python script would be able to process these changes into a new version of our responsive library.

The post Turning a Fixed-Size Object into a Responsive Element appeared first on CSS-Tricks.

Modern CSS Solutions for Old CSS Problems

Css Tricks - Mon, 05/11/2020 - 4:45am

This is a hell of a series by Stephanie Eckles. It’s a real pleasure watching CSS evolve and solve problems in clear and elegant ways.

Just today I ran across this little jab at CSS in a StackOverflow answer from 2013.

This particular jab was about CSS lacking a way to pause between @keyframe animations, which is still not something CSS can do without hacks. Aside from hand-wavy and ignorable “CSS is bad” statements, I see a lot less of this. CSS is just getting better.

Direct Link to ArticlePermalink

The post Modern CSS Solutions for Old CSS Problems appeared first on CSS-Tricks.

Chromium lands Flexbox gap

Css Tricks - Fri, 05/08/2020 - 1:22pm

I mentioned this the other day via Michelle Barker’s coverage, but here I’ll link to the official announcement. The main thing is that we’ll be getting gap with flexbox, which means:

.flex-parent { display: flex; gap: 1rem; } .flex-child { flex: 1; }

That’s excellent, as putting space in between flex items has been tough in the past. We have justify-content: space-between, which is nice sometimes, but that doesn’t allow you to explicitly tell the flex container how much space you want. For that, we’d typically use margin, but that means avoiding setting the margin on the first or last element depending on the direction of the margin — which is annoying gets complicated.

We have gap in CSS Grid and it’s way better. It’s great to have it in flexbox.

But it’s going to get weird for a minute. Safari doesn’t support it yet (nor stable Chrome) so we can’t just plop it out there and expect it to work with flexbox. But shouldn’t we be able to do an @supports query these days?

/* Nope, sorry. This "works" but it doesn't actually tell you if it works in *flexbox* or not. This works in grid in most browsers now, so it will pass. */ @supports (gap: 1rem) { .flex-parent { gap: 1rem; } }

That got weird because grid-gap was dropped in favor of just gap. I’m sure grid-gap will be supported forever because that’s generally how these things go, but we’re encouraged to use gap instead. So, you might say gap is a little overloaded, but that should shake out over time (a year?). It’s complicated a smidge more by the fact that column-gap is now going to gap as well. gap has a whole bunch of jobs.

I’d say I’m still in favor of the change, despite the overloading. Simpler mental modals are important for the long-term, and there isn’t exactly anything coming up to challenge CSS for styling in the browser. I’d bet my 2-year old daughter writes some CSS in her lifetime.

Direct Link to ArticlePermalink

The post Chromium lands Flexbox gap appeared first on CSS-Tricks.

prerender.js

Css Tricks - Fri, 05/08/2020 - 1:22pm

This is another player in the game of (pre)rendering the page of the link that you’re about to click on before you click it. The point of which is to get a performance boost for extremely little effort. You’re putting the browser to work getting that next page ready for, say, that half a second between where you hover a link and when you click it, when otherwise the browser wouldn’t have been doing anything.

Instant.page is another player, and I’ve been sufficiently convinced by its methodology to the extent that I run it here on this site right now. I don’t really know the difference between the two. And they aren’t the only players either. Google has quicklink and there’s guess-js for really exotic preloading.

It’s a bit of a pity that Safari and Firefox don’t support <link rel="prerender">, as it really seems to me the absolute easiest way to pull this off would be to drop that on the page where, on mouseover of a link, it points to the href of that link.

Direct Link to ArticlePermalink

The post prerender.js appeared first on CSS-Tricks.

Let’s Take a Deep Dive Into the CSS Contain Property

Css Tricks - Fri, 05/08/2020 - 4:33am

Compared to the past, modern browsers have become really efficient at rendering the tangled web of HTML, CSS, and JavaScript code a typical webpage provides. It takes a mere milliseconds to render the code we give it into something people can use.

What could we, as front-end developers, do to actually help the browser be even faster at rendering? There are the usual best practices that are so easy to forget with our modern tooling — especially in cases where we may not have as much control over generated code. We could keep our CSS under control, for instance, with fewer and simpler selectors. We could keep our HTML under control; keep the tree flatter with fewer nodes, and especially fewer children. We could keep our JavaScript under control; while being careful with our HTML and CSS manipulations.

Actually, modern frameworks such as Vue and React do help out a good bit with that last part.

I would like to explore a CSS property that we could use to help the browser figure out what calculations it can reduce in priority or maybe even skip altogether.

This property is called contain. Here is how MDN defines this property:

The contain CSS property allows an author to indicate that an element and its contents are, as much as possible, independent of the rest of the document tree. This allows the browser to recalculate layout, style, paint, size, or any combination of them for a limited area of the DOM and not the entire page, leading to obvious performance benefits.

A simple way to look at what this property provides is that we can give hints to the browser about the relationships of the various elements on the page. Not necessarily smaller elements, such as paragraphs or links, but larger groups such as sections or articles. Essentially, we’re talking about container elements that hold content — even content that can be dynamic in nature. Think of a typical SPA where dynamic content is being inserted and removed throughout the page, often independent of other content on the page.

A browser cannot predict the future of layout changes to the webpage that can happen from JavaScript inserting and removing content on the page. Even simple things as inserting a class name to an element, animating a DOM element, or just getting the dimensions of an element can cause a reflow and repaint of the page. Such things can be expensive and should be avoided, or at least be reduced as much as possible.

Developers can sort of predict the future because they’ll know about possible future changes based on the UX of the page design, such as when the user clicks on a button it will call for data to be inserted in a div located somewhere in the current view. We know that’s a possibility, but the browser does not. We also know that there’s a distinct possibility that inserting data in that div will not change anything visually, or otherwise, for other elements on the page.

Browser developers have spent a good amount of time optimizing the browser to handle such situations. There are various ways of helping the browser be more efficient in such situations, but more direct hints would be helpful. The contain property gives us a way to provide these hints.

The various ways to contain

The contain property has three values that can be used individually or in combination with one another: size, layout, and paint. It also has two shorthand values for common combinations: strict and content. Let’s cover the basics of each.

Please keep in mind that there are a number of rules and edge cases for each of these that are covered in the spec. I would imagine these will not be of much concern in most situations. Yet, if you get an undesired result, then a quick look at the spec might be handy.

There is also a style containment type in the spec that this article will not cover. The reason being that the style containment type is considered of little value at this time and is currently at-risk of being removed from the spec.

Size containment

size containment is actually a simple one to explain. When a container with this containment is involved in the layout calculations, the browser can skip quite a bit because it ignores the children of that container. It is expected the container will have a set height and width; otherwise, it collapses, and that is the only thing considered in layout of the page. It is treated as if it has no content whatsoever.

Consider that descendants can affect their container in terms of size, depending on the styles of the container. This has to be considered when calculating layout; with size containment, it most likely will not be considered. Once the container’s size has been resolved in relation to the page, then the layout of its descendants will be calculated.

size containment doesn’t really provide much in the way of optimizations. It is usually combined with one of the other values.

Although, one benefit it could provide is helping with JavaScript that alters the descendants of the container based on the size of the container, such as a container query type situation. In some circumstances, altering descendants based on the container’s size can cause the container to change size after the change was done to the descendants. Since a change in the container’s size can trigger another change in the descendants you could end up with a loop of changes. size containment can help prevent that loop.

Here’s a totally contrived example of this resizing loop concept:

CodePen Embed Fallback

In this example, clicking the start button will cause the red box to start growing, based on the size of the purple parent box, plus five pixels. As the purple box adjusts in size, a resize observer tells the red square to again resize based on the size of the parent. This causes the parent to resize again and so on. The code stops this process once the parent gets above 300 pixels to prevent the infinite loop.

The reset button, of course, puts everything back into place.

Clicking the checkbox “set size containment” sets different dimensions and the size containment on the purple box. Now when you click on the start button, the red box will resize itself based on the width of the purple box. True, it overflows the parent, but the point is that it only resizes the one time and stops; there’s no longer a loop.

If you click on the resize container button, the purple box will grow wider. After the delay, the red box will resize itself accordingly. Clicking the button again returns the purple box back to its original size and then the red box will resize again.

While it is possible to accomplish this behavior without use of the containment, you will miss out on the benefits. If this is a situation that can happen often in the page the containment helps out with page layout calculations. When the descendants change internal to the containment, the rest of the page behaves as if the changes never happened.

Layout containment

layout containment tells the browser that external elements neither affect the internal layout of the container element, nor does the internal layout of the container element affect external elements. So when the browser does layout calculations, it can assume that the various elements that have the layout containment won’t affect other elements. This can lower the amount of calculations that need to be done.

Another benefit is that related calculations could be delayed or lowered in priority if the container is off-screen or obscured. An example the spec provides is:

[…] for example, if the containing box is near the end of a block container, and you’re viewing the beginning of the block container

The container with layout containment becomes a containing box for absolute or fixed position descendants. This would be the same as applying a relative position to the container. So, keep that in mind how the container’s descendants may be affected when applying this type of containment.

On a similar note, the container gets a new stacking context, so z-index can be used the same as if a relative, absolute, or fixed position was applied. Although, setting the top, right, bottom, or left properties has no effect on the container.

Here’s a simple example of this:

CodePen Embed Fallback

Click the box and layout containment is toggled. When layout containment is applied, the two purple lines, which are absolute positioned, will shift to inside the purple box. This is because the purple box becomes a containing block with the containment. Another thing to note is that the container is now stacked on top of the green lines. This is because the container now has a new stacking context and follows those rules accordingly.

Paint containment

paint containment tells the browser none of the children of the container will ever be painted outside the boundaries of the container’s box dimensions. This is similar to placing overflow: hidden; on the container, but with a few differences.

For one, the container gets the same treatment as it does under layout containment: it becomes a containing block with its own stacking context. So, having positioned children inside paint containment will respect the container in terms of placement. If we were to duplicate the layout containment demo above but use paint containment instead, the outcome would be much the same. The difference being that the purple lines would not overflow the container when containment is applied, but would be clipped at the container’s border-box.

Another interesting benefit of paint containment is that the browser can skip that element’s descendants in paint calculations if it can detect that the container itself is not visible within the viewport. If the container is not in the viewport or obscured in some way, then it’s a guarantee that its descendants are not visible as well. As an example, think of a nav menu that normally sits off-screen to the left of the page and it slides in when a button is clicked. When that menu is in its normal state off-screen, the browser just skips trying to paint its contents.

Containments working together

These three containments provide different ways of influencing parts of rendering calculations performed by the browser. size containment tells the browser that this container should not cause positional shifting on the page when its contents change. layout containment tells the browser that this container’s descendants should not cause layout changes in elements outside of its container and vice-versa. paint containment tells the browser that this container’s content will never be painted outside of the container’s dimensions and, if the container is obscured, then don’t bother painting the contents at all.

Since each of these provide different optimizations, it would make sense to combine some of them. The spec actually allows for that. For example, we could use layout and paint together as values of the contain property like this:

.el { contain: layout paint; }

Since this is such an obvious thing to do, the spec actually provides two shorthand values:

ShorthandLonghandcontentlayout paintstrictlayout paint size

The content value will be the most common to use in a web project with a number of dynamic elements, such as large multiple containers that have content changing over time or from user activity.

The strict value would be useful for containers that have a defined size that will never change, even if the content changes. Once in place, it’ll stay the intended size. A simple example of that is a div that contains third-party external advertising content, at industry-defined dimensions, that has no relation to anything else on the page DOM-wise.

Performance benefits

This part of the article is tough to explain. The problem is that there isn’t much in the way of visuals about the performance benefits. Most of the benefits are behind-the-scenes optimizations that help the browser decide what to do on a layout or paint change.

As an attempt to show the contain property’s performance benefits, I made a simple example that changes the font-size on an element with several children. This sort of change would normally trigger a re-layout, which would also lead to a repaint of the page. The example covers the contain values of none, content, and strict.

CodePen Embed Fallback

The radio buttons change the value of the contain property being applied to the purple box in the center. The “change font-size” button will toggle the font-size of the contents of the purple box by switching classes. Unfortunately, this class change is also a potential trigger for re-layout. If you’re curious, here is a list of situations in JavaScript and then a similar list for CSS that trigger such layout and paint calculations. I bet there’s more than you think.

My totally unscientific process was to select the contain type, start a performance recording in Chome’s developer tools, click the button, wait for the font-size change, then stop the recording after another second or so. I did this three times for each containment type to be able to compare multiple recordings. The numbers for this type of comparison are in the low milliseconds each, but there’s enough of a difference to get a feel for the benefits. The numbers could potentially be quite different in a more real-world situation.

But there are a few things to note other than just the raw numbers.

When looking through the recording, I would find the relevant area in the timeline and focus there to select the task that covers the change. Then I would look at the event log of the task to see the details. The logged events were: recalculate style, layout, update layer tree, paint, and composite layers. Adding the times of all those gives us the total time of the task.

The event log with no containment.

One thing to note for the two containment types is that the paint event was logged twice. I’ll get back to that in a moment.

Completing the task at hand

Here are the total times for the three containment types, three runs each:

ContainmentRun 1Run 2Run 3Averagenone24 ms33.8 ms23.3 ms27.03 mscontent13.2 ms9 ms9.2 ms10.47 msstrict5.6 ms18.9 ms8.5 ms11 ms

The majority of the time was spent in layout. There were spikes here and there throughout the numbers, but remember that these are unscientific anecdotal results. In fact, the second run of strict containment had a much higher result than the other two runs; I just kept it in because such things do happen in the real world. Perhaps the music I was listening to at the time changed songs during that run, who knows. But you can see that the other two runs were much quicker.

So, by these numbers you can start to see that the contain property helps the browser render more efficiently. Now imagine my one small change being multiplied over the many changes made to the DOM and styling of a typical dynamic web page.

Where things get more interesting is in the details of the paint event.

Layout once, paint twice

Stick with me here. I promise it will make sense.

I’m going to use the demo above as the basis for the following descriptions. If you wish to follow along then go to the full version of the demo and open the DevTools. Note that you have to open up the details of the “frame” and not the “main” timeline once you run the performance tool to see what I’m about to describe.

Showing frame details open and main details closed in DevTools

I’m actually taking screenshots from the “fullpage” version since DevTools works better with that version. That said, the regular “full” version should give roughly the same idea.

The paint event only fired once in the event log for the task that had no containment at all. Typically, the event didn’t take too long, ranging from 0.2 ms to 3.6 ms. The deeper details is where it gets interesting. In those details, it notes that the area of paint was the entire page. In the event log, if you hover on the paint event, DevTools will even highlight the area of the page that was painted. The dimensions in this case will be whatever the size of your browser viewport happens to be. It will also note the layer root of the paint.

Paint event details

Note that the page area to the left in the image is highlighted, even outside of the purple box. Over to the right, are the dimensions of the paint to the screen. That’s roughly the size of the viewport in this instance. For a future comparison, note the #document as the layer root.

Keep in mind that browsers have the concept of layers for certain elements to help with painting. Layers are usually for elements that may overlap each other due to a new stacking context. An example of this is the way applying position: relative; and z-index: 1; to an element will cause the browser to create that element as a new layer. The contain property has the same effect.

There is a section in DevTools called “rendering” and it provides various tools to see how the browser renders the page. When selecting the checkbox named “Layer borders” we can see different things based on the containment. When the containment is none then you should see no layers beyond the typical static web page layers. Select content or strict and you can see the purple box get converted to its own layer and the rest of the layers for the page shift accordingly.

Layers with no containment Layers with containment

It may be hard to notice in the image, but after selecting content containment the purple box becomes its own layer and the page has a shift in layers behind the box. Also notice that in the top image the layer line goes across on top of the box, while in the second image the layer line is below the box.

I mentioned before that both content and strict causes the paint to fire twice. This is because two painting processes are done for two different reasons. In my demo the first event is for the purple box and the second is for the contents of the purple box.

Typically the first event will paint the purple box and report the dimensions of that box as part of the event. The box is now its own layer and enjoys the benefits that applies.

The second event is for the contents of the box since they are scrolling elements. As the spec explains; since the stacking context is guaranteed, scrolling elements can be painted into a single GPU layer. The dimensions reported in the second event is taller, the height of the scrolling elements. Possibly even narrower to make room for the scrollbar.

First paint event with content containment Second paint event with content containment

Note the difference in dimensions on the right of both of those images. Also, the layer root for both of those events is main.change instead of the #document seen above. The purple box is a main element, so only that element was painted as opposed as to whole document. You can see the box being highlighted as opposed to the whole page.

The benefits of this is that normally when scrolling elements come into view, they have to be painted. Scrolling elements in containment have already been painted and don’t require it again when coming into view. So we get some scrolling optimizations as well.

Again, this can be seen in the demo.

Back to that Rendering tab. This time, check “Scrolling performance issue” instead. When the containment is set to none, Chrome covers the purple box with an overlay that’s labeled “repaints on scroll.”

DevTools showing “repaints on scroll” with no containment

If you wish to see this happen live, check the “Paint flashing” option.

Please note: if flashing colors on the screen may present an issue for you in some way, please consider not checking the “Paint flashing” option. In the example I just described, not much changes on the page, but if one were to leave that checked and visited other sites, then reactions may be different.

With paint flashing enabled, you should see a paint indicator covering all the text within the purple box whenever you scroll inside it. Now change the containment to content or strict and then scroll again. After the first initial paint flash it should never reappear, but the scrollbar does show indications of painting while scrolling.

Paint flashing enabled and scrolling with no containment Paint flashing and scrolling with content containment

Also notice that the “repaints on scroll” overlay is gone on both forms of containment. In this case, containment has given us not only some performance boost in painting but in scrolling as well.

An interesting accidental discovery

As I was experimenting with the demo above and finding out how the paint and scrolling performance aspects worked, I came across an interesting issue. In one test, I had a simple box in the center of page, but with minimal styling. It was essentially an element that scrolls with lots of text content. I was applying content containment to the container element, but I wasn’t seeing the scrolling performance benefits described above.

The container was flagged with the “repaints on scroll” overlay and the paint flashing was the same as no containment applied, even though I knew for a fact that content containment was being applied to the container. So I started comparing my simple test against the more styled version I discussed above.

I eventually saw that if the background-color of the container is transparent, then the containment scroll performance benefits do not happen.

I ran a similar performance test where I would change the font-size of the contents to trigger the re-layout and repaint. Both tests had roughly the same results, with only difference that the first test had a transparent background-color and the second test had a proper background-color. By the numbers, it looks like the behind-the-scenes calculations are still more performant; only the paint events are different. It appears the element doesn’t become its own layer in the paint calculations with a transparent background-color.

The first test run only had one paint event in the event log. The second test run had the two paint events as I would expect. Without that background color, it seems the browser decides to skip the layer aspect of the containment. I even found that faking transparency by using the same color as the color behind the element works as well. My guess is if the container’s background is transparent then it must rely on whatever is underneath, making it impossible to separate the container to its own paint layer.

I made another version of the test demo that changes the background-color of the container element from transparent to the same color used for the background color of the body. Here are two screenshots showing the differences when using the various options in the Rendering panel in DevTools.

Rendering panel with transparent background-color

You can see the checkboxes that have been selected and the result to the container. Even with a content containment applied, the box has “repaints on scroll” as well as the green overlay showing painting while scrolling.

Rendering panel with background-color applied

In the second image, you can see that the same checkboxes are selected and a different result to the container. The “repaints on scroll” overlay is gone and the green overlay for painting is also gone. You can see the paint overlay on the scrollbar to show it was active.

Conclusion: make sure to apply some form of background color to your container when applying containment to get all the benefits.

Here’s what I used for the test:

CodePen Embed Fallback This is the bottom of the page

This article has covered the basics of the CSS contain property with its values, benefits, and potential performance gains. There are some excellent benefits to applying this property to certain elements in HTML; which elements need this applied is up to you. At least, that’s what I gather since I’m unaware of any specific guidance. The general idea is apply it to elements that are containers of other elements, especially those with some form of dynamic aspect to them.

Some possible scenarios: grid areas of a CSS grid, elements containing third-party content, and containers that have dynamic content based on user interaction. There shouldn’t be any harm in using the property in these cases, assuming you aren’t trying to contain an element that does, in fact, rely in some way on another element outside that containment.

Browser support is very strong. Safari is the only holdout at this point. You can still use the property regardless because the browser simply skips over that code without error if it doesn’t understand the property or its value.

So, feel free to start containing your stuff!

The post Let’s Take a Deep Dive Into the CSS Contain Property appeared first on CSS-Tricks.

I’m getting back to making videos

Css Tricks - Thu, 05/07/2020 - 2:51pm

It’s probably one part coronavirus, one part new-fancy-video setup, and one part “hey this is good for CodePen too,” but I’ve been doing more videos lately. It’s nice to be back in the swing of that for a minute. There’s something fun about coming back to an old familiar workflow.

Where do the videos get published? I’m a publish-on-your-own site kinda guy, as I’m sure you know, so there is a whole Videos section of this site where every video we’ve ever published lives. There is also a YouTube channel, of course, which is probably the most practical way for most people to subscribe. We’re about halfway to Wes Bos-level, so let’s go people!

I had literally forgotten about it, but ages ago when I set this up, I created a special RSS feed for the videos so I could submit it as a video podcast on iTunes. That’s all still there and working! An interesting side note is that this enables offline viewing, as most podcatchers can cache subscriptions. Why build an app when you get the core ability for free, right?

I keep the original videos, of course. On individual video pages, I show a YouTube player that could be somewhat easily swapped out for another player if something crazy happened, like YouTube closes down or drastically changed their business model in some way that makes it problematic to show videos with their player. The originals are stored in an S3 bucket. If you’re an MVP Supporter, I give you the original high-quality download link right on the video pages.

If your curious about my workflow, I’m still using ScreenFlow. I don’t make nearly enough use of it, but it feels good in that it’s fairly easy to use, very reliable and fast, and I can always learn and do more with it. Shooting my screen is easy and a built-in feature of ScreenFlow of course. I also have a Rode Podcaster on a boom arm at my desk so the audio is passable. And I just went through a whole process to use a DSLR camera at my desk too, and I think the quality from that is great. It’s all a little funny because I have this whole sound recording booth as well, with a $1,000 audio setup in there, but I only use that for podcasting. The lighting sucks in there, making it no good for video.

It’s this new desk setup that has inspired me to do more video, and I suspect it will continue! One thing I could really use is a new high quality intro video. Just like a five-second thing with refreshed aesthetics. Anyone do that kind of work?

The post I’m getting back to making videos appeared first on CSS-Tricks.

Exciting Things on the Horizon For CSS Layout

Css Tricks - Thu, 05/07/2020 - 2:51pm

Michelle Barker notes that it’s been a heck of a week for us CSS layout nerds.

  1. Firefox has long had the best DevTools for CSS Grid, but Chrome is about to catch up and go one bit better by visualizing grid line numbers and names.
  2. Firefox supports gap for display: flex, which is great, and now Chrome is getting that too.
  3. Firefox is trying out an idea for masonry layout.

Direct Link to ArticlePermalink

The post Exciting Things on the Horizon For CSS Layout appeared first on CSS-Tricks.

Creating an Accessible Range Slider with CSS

Css Tricks - Thu, 05/07/2020 - 8:17am

The accessibility trick is using <input type="range"> and wrestling it into shape with CSS rather than giving up and re-building it with divs or whatever and later forget about accessibility.

The most clever example uses an angled linear-gradient background making the input look like a volume slider where left = low and right = high.

CodePen Embed Fallback

Direct Link to ArticlePermalink

The post Creating an Accessible Range Slider with CSS appeared first on CSS-Tricks.

Making dark theme switcher with PostCSS.

Css Tricks - Wed, 05/06/2020 - 11:32pm

You have noticed that there is a new design trend that is floating around web design since 2019, the dark mode. Facebook, Apple, and Google both introduced the dark version of their software.

Why a dark theme

Most of you probably think this is just a trend that will disappear after some years, well, let me say that this is not like many other trends, dark UI provide different advantages and they are not something just related to the “designer mood”. Let’s see why a dark mode on your applications and websites are something useful.

Better for batteries

Pixels on a screen consume more energy to display light colors rather than dark ones. Consequently, devices’ batteries can save energy and improve their daily duration while using dark UI.

Better for dark environments

Most of us use their smartphone and laptops while at home. Such environments are typically not so bright. The dark mode can help the use of the application while indoor, without causing visual disturbances.

Better for people

Some people with — or without — visual diseases, like epilepsy, can have unfortunate events by being flashed by bright applications. Having a dark mode means being more accessible.

Preparing styles

A very simple theme switcher should offer at least 3 options:

  • Dark theme
  • Light theme
  • Automatic theme (should be on by default)

Wait, what’s the automatic theme? Well, modern operating systems allow users to change the global visual appearance by setting os-wide options that enable the dark or light mode. The automatic option make sure to respect the OS preference if the user has not specified any theme.

To make this even more simple, we’ll use PostCSS and a simple but useful plugin called postcss-dark-theme-class.

yarn add postcss-dark-theme-class

This plugin will do 70% of the work, once installed, add it to your PostCSS config and configure the selectors you want to use to activate the correct theme, which will be used by the plugin to generate the correct CSS:

module.exports = { plugins: [ /* ...other plugins */ require('postcss-dark-theme-class')({ darkSelector: '[data-theme="dark"]', lightSelector: '[data-theme="light"]' }) ] }

Once the plugin is up and running, we can start defining our dark and light themes using a CSS specific media query prefers-color-scheme. This special media query will handle the automatic part of our themes by applying the correct theme based on the user’s OS preferences:

:root { --accent-color: hsl(226deg 100% 50%); --global-background: hsl(0 0% 100%); --global-foreground: hsl(0 0% 0%); } @media (prefers-color-scheme: dark) { :root { --accent-color: hsl(226deg 100% 50%); --global-background: hsl(0 0% 0%); --global-foreground: hsl(0 0% 100%); } }

If the user is using a dark version of his OS, the set inside the media query will apply, overwriting others, otherwhise the set of properties outside the media query is used. Since it’s pure CSS, this behaviour is on by default.

Browsers will now adapt the color scheme automatically based on the users’ OS preferences. Nice done! &#x1f680; Now it’s time to make the theme switcher allow users to specify what theme to use, overriding the OS preference.

Preview(opens in a new tab)

Making the theme switcher

s we said, our switcher should have three options, we can use a simple select element, or build a set of buttons:

<button type="button" data-set-theme="auto">Auto</button> <button type="button" data-set-theme="dark">Dark</button> <button type="button" data-set-theme="light">Light</button>

We’ll build the switcher using vanilla JS, but you can do it with any framework you want, the concept is the same: we have to add the selectors we defined inside the PostCSS plugin to the root element, based on the clicked button.

const html = document.documentElement const themeButtons = document.querySelectorAll('[data-set-theme]'); themeButtons.forEach((button) => { const theme = button.dataset.setTheme; button.addEventListener('click', () => { html.dataset.theme = theme; }) }) This is a very basic and ugly JS example

Each time we click on a theme button, the value set as data-set-theme is applied as value of the data-theme attribute on the docEach time we click on a theme button, the value set as `data-set-theme` is applied as value of the `data-theme` attribute on the document root element, we also change the [aria-current] attribute.

Check it live:



Where is the magic?

The magic is made by postcss-dark-theme-class — which will add our [data-theme] custom attribute to the :root selectors we wrote — during the CSS transpilation. Here what it generates from our code:

/* Our automatic and user specified light theme */ :root { --accent-color: hsl(226deg, 100%, 50%); --global-background: hsl(0, 0%, 100%); --global-foreground: hsl(0, 0%, 0%); } /* Our automatic dark theme */ @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --accent-color: hsl(226deg, 100%, 50%); --global-background: hsl(0, 0%, 0%); --global-foreground: hsl(0, 0%, 100%); } } /* Our dark theme specified by the user */ :root[data-theme="dark"] { --accent-color: hsl(226deg, 100%, 50%); --global-background: hsl(0, 0%, 0%); --global-foreground: hsl(0, 0%, 100%); } Bonus tip

You may notice that the --accent-color custom property defined inside themes doesn’t change. If you have colors that will not change based on the theme, you can remove them from the prefers-color-scheme at-rule.

In this way, they will not be duplicated and the one defined outside the media query will always apply.

:root { --accent-color: hsl(226deg 100% 50%); --global-background: hsl(0 0% 100%); --global-foreground: hsl(0 0% 0%); } @media (prefers-color-scheme: dark) { :root { --global-background: hsl(0 0% 0%); --global-foreground: hsl(0 0% 100%); } }

The post Making dark theme switcher with PostCSS. appeared first on CSS-Tricks.

Static Hoisting

Css Tricks - Wed, 05/06/2020 - 11:09am

The other day in “Static or not?” I said:

[…] serving HTML from a CDN is some feat.

What I meant is that serving resources like images, CSS, and JavaScript from a CDN is fairly straightforward. The industry at large has been doing that for many years. An asset with a URL can be moved to a CDN and served from it. Changes to that asset are usually handled by changing the URL (e.g. style.324535.css, style.css?v=345434 or the like) so that we can take full advantage of browser cache. But HTML is a little different. The URLs to our HTML are the URLs of our public-facing websites and those URLs don’t change.

Historically, we’ve said “oh well” to this. Our web servers will serve our HTML and we’ll just do the best we can with performance there. But the Jamstack approach is changing that by saying, actually, we’ll serve that HTML from a CDN as well.

Guillermo Rauch calls that “hoisting” and likens it to how JavaScript hoists declarations higher in code. Jamstack hoists static assets higher in the hosting stack.

What Jamstack as a software architecture has now made possible, however, is to hoisting the results of computation to the edge, right next to where your visitors are.

A core tenet of Jamstack has been to pre-render (pre-compute) as much as possible, which has given prominence to static site generation. The key idea is that computation that would have happened later on, in the request’s timeline, has now been shifted to the build phase, performed once and made available for all users to share.

Hoisting, notably, happens automatically. What can be hoisted will be hoisted. But things that need servers to run (e.g. cloud functions and API stuff) can still do that. Getting even more complex, in our talk with Brian Leroux, Dave and I got into how even the results of cloud function execution can be put on a CDN and cached.

Direct Link to ArticlePermalink

The post Static Hoisting appeared first on CSS-Tricks.

How to Use Block Variations in WordPress

Css Tricks - Wed, 05/06/2020 - 4:43am

WordPress 5.4 was released not so long ago and, along with other improvements and bug fixes, it introduced a feature called Block Variations. I had a chance to use it on one of my recent projects and am so pleasantly surprised with how smart this feature is. I actually think it hasn’t received the attention it deserves, which is why I decided to write this article.

What is a Block Variation?

Block Variations allow developers to define instances of existing blocks. An example that you’ll see below is a quote block. Perhaps your site has three variations of how to display a quote on your site. A Block Variation can be created for each one so that they are all styled differently. This sounds awfully familiar with how Block Styles, but the concept of variations goes a bit further than that, as we’ll see.

How are Block Variations different from Block Styles?

Fair question. Block variations appear in the inserter as separate blocks with unique names and (optionally) icons and can have pre-filled custom attributes, and inner blocks.

Block Styles are designed to alter the look of the block. In fact, a Block Style is a fancy way of adding a custom class to a block using the Block options in the post editor.

The difference is clear when you consider how each one is used in the post editor. Let’s say we register a new Block Style called “Fancy Quote.” We do that by extending the core “Quote” block like this example from the Block Editor Handbook:

wp.blocks.registerBlockStyle(   'core/quote',   {     name: 'fancy-quote',     label: 'Fancy Quote'   }, );

This adds a .is-style-fancy-quote class to the Quote block settings in the post editor.

We now have a Fancy Quote option in the Block options under “Styles” and the class for it filled in for us.

Even though it sort of sounds like it would do the same thing (which it technically can), a Block Variation can be used to pre-fill custom attributes (including custom classes) and inner blocks. They’re actually registered as separate blocks.

Let’s take a closer look at the API and what block variations can do.

Creating a Block Variation

The API for registering Block Variations is very similar that of the Block Style we just looked at:

wp.blocks.registerBlockVariation(   'core/quote',   {     name: 'fancy-quote',     title: 'Fancy Quote',   }, );

The registerBlockVariation function accepts the name of the block (in our case it is core/quote) and an object (or an array of objects) describing the variation(s).

The code above doesn’t do much by default, but it does add “Fancy Quote” to the list of available blocks.

We now have two different “quote” blocks available to drop into the post.

To take full advantage of the variation. we need to provide more details in the object describing it. The list is covered in the Make WordPress post, but I’ll share it here and provide additional comments.

  • name – The unique and machine-readable name of the variation. Following the examples on Github and Make post it’s safe to assume that the best practice is to use kebab-case for naming variations.
  • title – A human-readable variation title. This is what appears under the icon in the Inserter.
  • description – A detailed variation description. Appears in the Inserter as well. If empty, the default block description will be used. (Optional)
  • icon – An icon for the variation. Can be a Dashicons slug, an SVG or an object. Follows the same declaration pattern as in registerBlockType. (Optional)
  • isDefault – Indicates whether the current variation is the default one. Defaults to false. In case of our example, if we set it to true, the Fancy Quote block will be the only Quote block available in the inserter. (Optional)
  • attributes – Values that override block attributes. These are block-specific. You can set the level for the Heading block or height for Spacer, for example.
  • innerBlocks – Initial configuration of nested blocks. Only applies to blocks that allow inner blocks in the first place, like Columns, Cover, or Group. We’ll cover this in one of the examples. (Optional)
  • example – Example provides structured data for the block preview. You can set it to undefined to disable the preview shown for the block type. This is the same as the example field in registerBlockType. (Optional) There’s more information available on this parameter.
  • scope – The list of scopes where the variation is applicable. When not provided, it assumes all available scopes. Available options are block and inserter. We’ll cover this in detail in one of the examples.

Many of you may wonder why we need this extra layer of abstraction. Let me try to answer that with a few use cases (one form my recent project).

Use case: Buttons with different widths

Let’s say you have a design system with two types of buttons: Fill and Outline.

Fill and Outline button styles in the design system

Lucky you, because these are the default styles for buttons in WordPress. No need to register any new styles or hack the editor. All you have to do is write some CSS for each style and call it a day. Life is good and everybody’s happy.

But then you look in the design spec again and notice that there is a little twist. The buttons come in three widths: Regular, Wide, and Full.

Fill and Outline button styles with different width variations

Dammit! You are a little upset because you now have two options:

  1. Write two extra classes for the new button sizes (say, .is-wide and .is-full), then teach the client to use the Advanced panel in the editor to add those classes and write a manual where you explain what each class does. Or…
  2. Register four(!) new styles that go in the Block options: Fill Wide, Fill Full, Outline Wide, and Outline Full.

Neither of those options are exactly elegant. (BTW, what is Fill Full exactly? Quite an unfortunate mouthful!)

There are two more options that I didn’t include in the list:

  • Filter the button block and add a custom width control to it
  • Build a custom block from scratch.

These obviously feel like heavy lifts for such a simple task.

Enter Block Variations! By adding just two variations, Full and Wide, we can keep things clean and simple:

wp.blocks.registerBlockVariation(   'core/buttons',   [     {       name: 'wide',       title: 'Wide Buttons',       attributes: {         className: 'is-wide'       },   },   {       name: 'full',       title: 'Full Buttons',       attributes: {         className: 'is-full'       },     }   ] );

This is the same as adding a custom class to the Buttons block, but in a neat and elegant way that can be dropped directly into a post from the Block Inserter:

Button variations in the inserter

Life is good and everybody is happy again! So what did we learn from this example?

  • It shows that Block Variations are not designed to replace Block Styles. In fact, they can work pretty well together even if the variation just adds a class to a block.
  • It demos how to register multiple variations in a single declaration.
Use case: Repeating column layouts

Let’s say you are a designer and have a portfolio website with case studies. Each case study has an intro section with the name of the project, client information, and a description of your role on the project. It might look something like this:

The type of work (left), who it was for (center) and your role on it (right)

The problem is that it’s a bit tedious to build this part of the layout every time you create a new portfolio case study — especially because the Client and My Role headings never change. You are only editing the main title and two paragraphs.

With Block Variations, you can create a variation of a core Columns block called Project Intro that will have the columns, and inner blocks already defined. This example is a bit more involved, so we’ll build it out step-by-step.

Let’s start with registering the variation:

wp.blocks.registerBlockVariation(   'core/columns', {     name: 'project-intro',     title: 'Project Intro',     scope: ['inserter'],     innerBlocks: [       ['core/column'],       ['core/column'],       ['core/column'],     ],   } );

We are taking this example a bit further than the first one, so why not add a custom portfolio icon from the Dashicons library that’s baked right into WordPress? We do that with the icon property.

wp.blocks.registerBlockVariation(   'core/columns', {     name: 'project-intro',     title: 'Project Intro',     icon: 'portfolio',     scope: ['inserter'],     innerBlocks: [       ['core/column'],       ['core/column'],       ['core/column'],     ],   } );

This will make the block available in the block menu with our icon:

The next important thing happens on where we add inner blocks:

wp.blocks.registerBlockVariation(   'core/columns', {     name: 'project-intro',     title: 'Project Intro',     icon: 'portfolio',     scope: ['inserter'],     innerBlocks: [       ['core/column'],       ['core/column'],       ['core/column'],     ],   } );

But this only gives us three empty columns. Let’s add starter content and inner blocks to each of them. We can use the same pattern we use to declare a block template in the InnerBlocks component. We can add an object with block attributes as a second element in the array describing the block, and an array of inner blocks as the third element.

The first column will look like this:

['core/column', {}, [   ['core/heading', { level: 2, placeholder: 'Project Title'} ], ]]

…and the complete block variation is like this:

wp.blocks.registerBlockVariation (   'core/columns', {     name: 'project-intro',     title: 'Project Intro',     icon: 'portfolio',     scope: ['inserter'],     innerBlocks: [       ['core/column', {}, [         ['core/heading', { level: 2, placeholder: 'Project Title' }],       ]],       ['core/column', {}, [         ['core/heading', { level: 3, content: 'Client' }],         ['core/paragraph', { placeholder: 'Enter client info' }],       ]],       ['core/column', {}, [         ['core/heading', { level: 3, content: 'My Role' }],         ['core/paragraph', { placeholder: 'Describe your role' }],       ]],     ],   } );

Cool, now we can insert the whole section with just one click. Okay, it’s a few clicks, but still faster than without using the variations.

So what did we learn from this example?

  • And demos how to use the inner blocks within the variation
  • It shows how to define a custom icon for a variation
Use case: Four-column layout

You already know that columns are a default block type, and that there are a handful of options for different types of columns. A four-column layout isn’t one of them, so we can build that. But this introduces a new concept as well: scoping in context of block variations.

Some core blocks, like Columns, already offer variations out of the box. You can choose one of them after you insert the block on the page:

Block-scoped variations

Let’s say you use a four-column layout on your website as often as you use two-column one. That’s unfortunate, because there is no shortcut button to create four-column layout. Creating one is a bit annoying because it takes extra clicks to get to the Columns control after the block is inserted:

So, what can you do to improve this workflow? Right, you can add a Block Variation that will create a four-column layout. The only difference this time, compared to previous examples, is that it makes much more sense to include this variation inside the block placeholder, next to all other column layouts.

That is exactly what the scope option is for. If you set it to [block], the variation will not appear in the Block Inserter but in the variations once the block has been inserted.

wp.blocks.registerBlockVariation(   'core/columns', {     name: 'four-columns',     title: 'Four columns; equal split',     icon: <svg ... />,     scope: ['block'], // Highlight     innerBlocks: [       ['core/column'],       ['core/column'],       ['core/column'],       ['core/column'],     ],   } ); Hey, now we have a four-column option!

Isn’t that sweet?!

I’ve omitted the full SVG code for the icon, but it’s available if you need it.

To sum up scope: If it isn’t declared, the variation will appear in the Block Inserter and inside the block placeholder — specifically for blocks that support block-scoped variations. 

If we were to remove the scope parameter from the example above, here’s how the variation would appear in the inserter:

Keep in mind that the icon sizes for variations within the block and and the block icons size are different. The custom icon for columns was intended for the block scope, that’s why it looks a bit out-of-place in this example.

So what did we learn from this example?

  • It explains the difference between the block and inserter scope for the variation.
  • We learned how to use SVG for variation icon.
That’s it!

As you can see, Block Variations are pretty powerful for building a lot of things, from different variations of buttons to complete page layouts.

I’d like to wrap this up with a quick recap of different APIs for block customizations and when to use them:

  • Use Block Styles if you need to alter the appearance of the block and adding a CSS class is enough for that.
  • Use Block Variations if you need to specify the default attributes for the block and/or add inner blocks to it.
  • If that’s not enough and you need to change the markup of the block, you are probably looking into filtering the block or creating a new one from scratch.

If you’ve had a chance to play with Block Variation, let me know what you think of them in the comments!

Resources

The post How to Use Block Variations in WordPress appeared first on CSS-Tricks.

How to Create Custom WordPress Editor Blocks in 2020

Css Tricks - Wed, 05/06/2020 - 4:43am

Peter Tasker on creating blocks right now:

It’s fairly straightforward these days to get set up with the WP CLI ‘scaffold’ command. This command will set up a WordPress theme or plugin with a ‘blocks’ folder that contains the PHP and base CSS and JavaScript required to create a custom block. The only drawback that I noticed is that the JavaScript uses the old ES5 syntax rather than modern ESNext. Modern JavaScript allows us to write more concise code and use JSX in our custom block code.

You can also use the ‘create-guten-block’ tool by Ahmad Awais. It gives you a lot of the boilerplate stuff you need out of the box, like Webpack, ESNext support etc. Setting it up is fairly straightforward, and it’s similar to Create React App.

I’ve used create-guten-block for the handful of custom blocks I’ve made so far, and have found it a pretty nice experience.

But… I feel like I just sort of lucked into being comfortable with all this. I have one foot in WordPress development and just so happen to have one foot in React development. Building blocks with both technologies together feels decently natural to me. If blocks were Angular or something, I feel like I might not have even given it a shot.

I’ll echo this sentiment:

I also found it really annoying working on a block that’s actively changing in code. Every time you reload Gutenberg, you’ll get the “This block appears to have been modified externally…” message because the markup of the block has changed.

I get why it’s throwing the error, but it slows you down.

At the end, Peter mentions the approach of building blocks that Advanced Custom Fields has. It almost feels like a weird bizarro-reverso world. The ACF approach seems more like what WordPress would have done in a normal world (building blocks with just PHP and templating) and third-parties would be the ones adding all the fancy React stuff.

Direct Link to ArticlePermalink

The post How to Create Custom WordPress Editor Blocks in 2020 appeared first on CSS-Tricks.

Syndicate content
©2003 - Present Akamai Design & Development.