Developer News

Fading in a Page on Load with CSS & JavaScript

Css Tricks - Wed, 01/13/2021 - 12:44pm

Louis Lazaris demonstrates a very simple way of doing this.

  1. Hide the body (with JavaScript) right away with a CSS class that declares opacity: 0
  2. Wait for all the JavaScript to execute
  3. Unhide the body by transitioning it back to opacity: 1

Like this:

CodePen Embed Fallback

Louis demonstrates a callback method, as well as mentioning you could wait for window.load or a DOM Ready event. I suppose you could also just have the line that sets the className to visible as the very last line of script that runs like I did above.

Louis knows it’s not particularly en vogue:

I know nowadays we’re obsessed in this industry with gaining every millisecond in page performance. But in a couple of projects that I recently overhauled, I added a subtle and clean loading mechanism that I think makes the experience nicer, even if it does ultimately slightly delay the time that the user is able to start interacting with my page.

I think of stuff like font-display: swap; which is dedicated to rendering your text as absolutely fast as possible, FOUT be damned, rather than chiller options.

Direct Link to ArticlePermalink

The post Fading in a Page on Load with CSS & JavaScript appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Two Issues Styling the Details Element and How to Solve Them

Css Tricks - Wed, 01/13/2021 - 5:56am

In the not-too-distant past, even basic accordion-like interactions required JavaScript event listeners or some CSS… trickery. And, depending on the solution used, editing the underlying HTML could get complicated.

Now, the <details> and <summary> elements (which combine to form what’s called a “disclosure widget”) have made creation and maintenance of these components relatively trivial.

At my job, we use them for things like frequently asked questions.

Pretty standard question/answer format There are a couple of issues to consider

Because expand-and-collapse interactivity is already baked into the <details> and <summary> HTML tags, you can now make disclosure widgets without any JavaScript or CSS. But you still might want some. Left unstyled, <details> disclosure widgets present us with two issues.

Issue 1: The <summary> cursor

Though the <summary> section invites interaction, the element’s default cursor is a text selection icon rather than the pointing finger you may expect:

We get the text cursor but might prefer the pointer to indicate interaction instead. Issue 2: Nested block elements in <summary>

Nesting a block-level element (e.g. a heading) inside a <summary> element pushes that content down below the arrow marker, rather than keeping it inline:

Block-level elements won’t share space with the summary marker. The CSS Reset fix

To remedy these issues, we can add the following two styles to the reset section of our stylesheets:

details summary { cursor: pointer; } details summary > * { display: inline; }

Read on for more on each issue and its respective solution.

Changing the <summary> cursor value

When users hover over an element on a page, we always want them to see a cursor “that reflects the expected user interaction on that element.”

We touched briefly on the fact that, although <summary> elements are interactive (like a link or form button), its default cursor is not the pointing finger we typically see for such elements. Instead, we get the text cursor, which we usually expect when entering or selecting text on a page.

To fix this, switch the cursor’s value to pointer:

details summary { cursor: pointer; } CodePen Embed Fallback

Some notable sites already include this property when they style <details> elements. The MDN Web Docs page on the element itself does exactly that. GitHub also uses disclosure widgets for certain items, like the actions to watch, star and fork a repo.

GitHub uses cursor: pointer on the <summary> element of its disclosure widget menus. 

I’m guessing the default cursor: text value was chosen to indicate that the summary text can (along with the rest of a disclosure widget’s content) be selected by the user. But, in most cases, I feel it’s more important to indicate that the <summary> element is interactive.

Summary text is still selectable, even after we’ve changed the cursor value from text to pointer. Note that changing the cursor only affects appearance, and not its functionality.

Displaying nested <summary> contents inline

Inside each <summary> section of the FAQ entries I shared earlier, I usually enclose the question in an appropriate heading tag (depending on the page outline):

<details> <summary> <h3>Will my child's 504 Plan be implemented?</h3> </summary> <p>Yes. Similar to the Spring, case managers will reach out to students.</p> </details>

Nesting a heading inside <summary> can be helpful for a few reasons:

  • Consistent visual styling. I like my FAQ questions to look like other headings on my pages.
  • Using headings keeps the page structure valid for users of Internet Explorer and pre-Chromium versions of Edge, which don’t support <details> elements. (In these browsers, such content is always visible, rather than interactive.)
  • Proper headings can help users of assistive technologies navigate within pages. (That said, headings within <summary> elements pose a unique case, as explained in detail below. Some screen readers interpret these headings as what they are, but others don’t.)
Headings vs. buttons

Keep in mind that the <summary> element is a bit of an odd duck. It operates like a button in many ways. In fact, it even has implicit role=button ARIA mapping. But, very much unlike buttons, headings are allowed to be nested directly inside <summary> elements.

This poses us — and browser and assistive technology developers — with a contradiction:

  • Headings are permitted in <summary> elements to provide in-page navigational assistance.
  • Buttons strip the semantics out of anything (like headings) nested within them.

Unfortunately, assistive technologies are inconsistent in how they’ve handled this situation. Some screen-reading technologies, like NVDA and Apple’s VoiceOver, do acknowledge headings inside <summary> elements. JAWS, on the other hand, does not.

What this means for us is that, when we place a heading inside a <summary>, we can style the heading’s appearance. But we cannot guarantee our heading will actually be interpreted as a heading!

In other words, it probably doesn’t hurt to put a heading there. It just may not always help.

Inline all the things

When using a heading tag (or another block element) directly inside our <summary>, we’ll probably want to change its display style to inline. Otherwise, we’ll get some undesired wrapping, like the expand/collapse arrow icon displayed above the heading, instead of beside it.

We can use the following CSS to apply a display value of inline to every heading — and to any other element nested directly inside the <summary>:

details summary > * { display: inline; } CodePen Embed Fallback

A couple notes on this technique. First, I recommend using inline, and not inline-block, as the line wrapping issue still occurs with inline-block when the heading text extends beyond one line.

Second, rather than changing the display value of the nested elements, you might be tempted to replace the <summary> element’s default display: list-item value with display: flex. At least I was! However, if we do this, the arrow marker will disappear. Whoops!

Bonus tip: Excluding Internet Explorer from your styles

I mentioned earlier that Internet Explorer and pre-Chromium (a.k.a. EdgeHTML) versions of Edge don’t support <details> elements. So, unless we’re using polyfills for these browsers, we may want to make sure our custom disclosure widget styles aren’t applied for them. Otherwise, we end up with a situation where all our inline styling garbles the element.

Inline <summary> headings could have odd or undesirable effects in Internet Explorer and EdgeHTML.

Plus, the <summary> element is no longer interactive when this happens, meaning the cursor’s default text style is more appropriate than pointer.

If we decide that we want our reset styles to target only the appropriate browsers, we can add a feature query that prevents IE and EdgeHTML from ever having our styles applied. Here’s how we do that using @supports to detect a feature only those browsers support:

@supports not (-ms-ime-align: auto) { details summary { cursor: pointer; } details summary > * { display: inline; } /* Plus any other <details>/<summary> styles you want IE to ignore. }

IE actually doesn’t support feature queries at all, so it will ignore everything in the above block, which is fine! EdgeHTML does support feature queries, but it too will not apply anything within the block, as it is the only browser engine that supports -ms-ime-align.

The main caveat here is that there are also a few older versions of Chrome (namely 12-27) and Safari (macOS and iOS versions 6-8) that do support <details> but don’t support feature queries. Using a feature query means that these browsers, which account for about 0.06% of global usage (as of January 2021), will not apply our custom disclosure widget styles, either.

Using a @supports selector(details) block, instead of @supports not (-ms-ime-align: auto), would be an ideal solution. But selector queries have even less browser support than property-based feature queries.

Final thoughts

Once we’ve got our HTML structure set and our two CSS reset styles added, we can spruce up all our disclosure widgets however else we like. Even some simple border and background color styles can go a long way for aesthetics and usability. Just know that customizing the <summary> markers can get a little complicated!

CodePen Embed Fallback

The post Two Issues Styling the Details Element and How to Solve Them appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

A (terrible?) way to do footnotes in HTML

Css Tricks - Wed, 01/13/2021 - 5:53am

Terence Eden poked around with a way to do footnotes using the <details>/<summary> elements. I think it’s kind of clever. Rather than a hyperlink that jumps down to explain the footnote elsewhere, the details are right there next to the text. I like that proximity in the code. Plus, you get the native open/close interactivity of the disclosure widget.

It’s got some tricky parts though. The <details> element is block-level, so it needs to become inline to be the footnote, and sized/positioned to look “right.” I think it’s a shame that it won’t sit within a <p> tag, so that makes it impractical for my own usage.

Craig Shoemaker in the comments forked the original to fiddle with the CSS, and that inspired me to do the same.

Rather than display the footnote text itself right inline (which is extra-tricky), I moved that content to a fixed-position location at the bottom of the page:

CodePen Embed Fallback

I’m not 100% convinced it’s a good idea, but I’m also not convinced it’s a terrible one.

The post A (terrible?) way to do footnotes in HTML appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

The WordPress.com Business Plan is way more powerful than you think

Css Tricks - Tue, 01/12/2021 - 10:14am

WordPress.com is where you go to use WordPress that is completely hosted for you. You don’t have to worry about anything but building your site. There is a free plan to get started with, and paid plans that offer more features. The Business plan is particularly interesting, and my guess is that most people don’t fully understand everything that it unlocks for you, so let’s dig into that.

You get straight up SFTP access to your site.

Here’s me using Transmit to pop right into one of my sites over SFTP.

What this means is that you can do local WordPress development like you normally would, then use real deployment tools to kick your work out to production (which is your WordPress.com site). That’s what I do with Buddy. (Here a screencast demonstrating the workflow.)

That means real control.

I can upload and use whatever plugins I want. I can upload and use whatever themes I want. The database too — I get literal direct MySQL access.

I can even manage what PHP version the site uses. That’s not something I’d normally even need to do, but that’s just how much access there is.

A big jump in storage.

200 GB. You’ll probably never get anywhere near that limit, unless you are uploading video, and if you are, now you’ve got the space to do it.

Backups you’ll probably actually use.

You don’t have to worry about anything nasty happening on WordPress.com, like your server being hacked and losing all your data or anything. So in that sense, WordPress.com is handling your backups for you. But with the Business plan, you’ll see a backup log right in your dashboard:

That’s a backup of your theme, data, assets… everything. You can download it anytime you like.

The clutch feature? You can restore things to any point in time with the click of a button.

Powered by a global CDN

Not every site on WordPress.com is upgraded to the global CDN. Yours will be if it’s on the Business plan. That means speed, and speed is important for every reason, including SEO. And speaking of SEO tools, those are unlocked for you on the Business plan as well.

Some of the best themes unlock at the Premium/Business plan level.

You can buy them one-off, but you don’t have to if you’re on the Business plan because it opens the door for more playing around. This Aquene theme is pretty stylish with a high-end design:

It’s only $300/year.

(Or $33/month billed monthly.)

So it’s not ultra-budget hosting, but the price tag is a lot less if you consider all the things we covered here and how much they cost if you were to cobble something together yourself. And we didn’t even talk about support, which is baked right into the plan.

Hosting, backups, monitoring, performance, security, plugins, themes, and support — toss in a free year or domain registration, and that’s a lot of website for $300.

They have less expensive plans as well. But the Business plan is the level where serious control, speed, and security kick in.

Coupon code CSSTRICKS gets you 15% off the $300/year Business Plan. Valid until the end of February 2021.

The post The WordPress.com Business Plan is way more powerful than you think appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

How to Add Commas Between a List of Items Dynamically with CSS

Css Tricks - Tue, 01/12/2021 - 5:53am

Imagine you have a list of items. Say, fruit: Banana, Apple, Orange, Pear, Nectarine

We could put those commas (,) in the HTML, but let’s look at how we could do that in CSS instead, giving us an extra level of control. We’ll make sure that last item doesn’t have a comma while we’re at it.

I needed this for a real project recently, and part of the requirements were that any of the items in the list could be hidden/revealed via JavaScript. The commas needed to work correctly no matter which items were currently shown.

One solution I found rather elegant solution is using general sibling combinator. We’ll get to that in a minute. Let’s start with some example HTML. Say you start out with a list of fruits:

<ul class="fruits"> <li class="fruit on">Banana</li> <li class="fruit on">Apple</li> <li class="fruit on">Orange</li> <li class="fruit on">Pear</li> <li class="fruit on">Nectarine</li> </ul>

And some basic CSS to make them appear in a list:

.fruits { display: flex; padding-inline-start: 0; list-style: none; } .fruit { display: none; /* hidden by default */ } .fruit.on { /* JavaScript-added class to reveal list items */ display: inline-block; }

Now say things happen inside this interface, like a user toggles controls that filter out all fruits that grow in cold climates. Now a different set of fruits is shown, so the fruit.on class is manipulated with the classList API.

So far, our HTML and CSS would create a list like this:

BananaOrangeNectarine

Now we can reach for that general sibling combinator to apply a comma-and-space between any two on elements:

.fruit.on ~ .fruit.on::before { content: ', '; }

Nice!

You might be thinking: why not just apply commas to all the list items and remove it from the last with something like :last-child or :last-of-type. The trouble with that is the last child might be “off” at any given time. So what we really want is the last item that is “on,” which isn’t easily possible in CSS, since there is nothing like “last of class” available. Hence, the general sibling combinator trick!

In the UI, I used max-width instead of display and toggled that between 0 and a reasonable maximum value so that I could use transitions to push items on and off more naturally, making it easier for the user to see which items are being added or removed from the list. You can add the same effect to the pseudo-element as well to make it super smooth.

Here’s a demo with a couple of examples that are both slight variations. The fruits example uses a hidden class instead of on, and the veggies example has the animations. SCSS is also used here for the nesting:

CodePen Embed Fallback

I hope this helps others looking for something similar!

The post How to Add Commas Between a List of Items Dynamically with CSS appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Building Flexible Components With Transparency

Css Tricks - Tue, 01/12/2021 - 5:44am

Good thinking from Paul Hebert on the Cloudfour blog about colorizing a component. You might look at a design comp and see a card component with a header background of #dddddd, content background of #ffffff, on an overall background of #eeeeee. OK, easy enough. But what if the overall background becomes #dddddd? Now your header looks lost within it.

That darker header? Design-wise, it’s not being exactly #dddddd that’s important; it’s about looking slightly darker than the background. When that’s the case, a background of, say rgba(0, 0, 0, 0.135) is more resiliant.

That will then remain resilient against backgrounds of any kind.

CodePen Embed Fallback

Direct Link to ArticlePermalink

The post Building Flexible Components With Transparency appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Flash’s Web Tech Legacy

Css Tricks - Mon, 01/11/2021 - 11:54am

Tiffany B. Brown on how Flash paved the way for some things we might think of as fairly modern web technologies:

Flash wasn’t just good for playing multimedia. It was also good for manipulating it. Using ActionScript, you could pan audio, adjusting the input for the user’s left and right speakers, perhaps when they shifted their mouse from one side of the screen to the other. Now we can do that using the Web Audio API.

Web Storage and the localStorage/ sessionStorage APIs are conceptually similar to SharedObjects, or Flash cookies. And the demand for rich web typography enabled by Flash and sIFR, helped bring us @font-face, WOFF, and web-licensed fonts.

Flash also popularized the idea of the cross-domain policy file, an XML file that specifies whether one domain can read the content and data of another. It’s a precursor to cross-origin resource sharing (CORS), which uses HTTP headers instead of an XML configuration file.

Mike Davidson had some nostolgic thoughts as well:

Most technology is transitional if your window is long enough. Cassette tapes showed us that taking our music with us was possible. Tapes served their purpose until compact discs and then MP3s came along. Then they took their rightful place in history alongside other evolutionary technologies. Flash showed us where we could go, without ever promising that it would be the long-term solution once we got there.

Direct Link to ArticlePermalink

The post Flash’s Web Tech Legacy appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Animating with Lottie

Css Tricks - Mon, 01/11/2021 - 6:09am

I believe animation on the web is not only fun, but engaging in such a way that it has converted site visitors into customers. Think of the “Like” button on Twitter. When you “like” a tweet, tiny colorful bubbles spread around the heart button while it appears to morph into a circle around the button before settling into the final “liked” state, a red fill. It would be much less exciting if the heart just went from being outlined to filled. That excitement and satisfaction is a perfect example of how animation can be used to enhance user experience.

This article is going to introduce the concept of rendering Adobe After Effects animation on the web with Lottie, which can make advanced animations— like that Twitter button — achievable.

Bodymovin is a plugin for Adobe After Effects that exports animations as JSON, and Lottie is the library that renders them natively on mobile and on the web. It was created by Hernan Torrisi. If you’re thinking Oh, I don’t use After Effects, this article is probably not for me, hold on just a moment. I don’t use After Effects either, but I’ve used Lottie in a project.

You don’t have to use Lottie to do animation on the web, of course. An alternative is to design animations from scratch. But that can be time-consuming, especially for the complex types of animations that Lottie is good at. Another alternative is using GIF animations, which are limitless in the types of animation they can display, but are typically double the size of the JSON files that Bodymovin produces.

So let’s jump into it and see how it works.

Get the JSON

To use Lottie, we need a JSON file containing the animation from After Effects. Luckily for us, Icons8 has a lot of free animated icons here in JSON, GIF, and After Effects formats.

Add the script to HTML

We also need to get the Bodymovin player’s JavaScript library in our HTML, and call its loadAnimation() method. The fundamentals are demonstrated here:

<div id="icon-container"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/bodymovin/5.7.4/lottie.min.js"> <script> var animation = bodymovin.loadAnimation({ // animationData: { /* ... */ }, container: document.getElementById('icon-container'), // required path: 'data.json', // required renderer: 'svg', // required loop: true, // optional autoplay: true, // optional name: "Demo Animation", // optional }); </script> Activate the animation

After the animation has loaded in the container, we can configure it to how we want it to be activated and what action should activate it with event listeners. Her are the properties we have to work with:

  • container: the DOM element that the animation is loaded into
  • path: the relative path of the JSON file that contains the animation
  • renderer: the format of the animation, including SVG, canvas, and HTML
  • loop: boolean to specify whether or not the animation should loop
  • autoplay: boolean to specify whether or not the animation should play as soon as it’s loaded
  • name: animation name for future referencing

Note in the earlier example that the animationData property is commented out. It is mutually exclusive with the path property and is an object that contains the exported animated data.

Let’s try an example

I’d like to demonstrate how to use Lottie with this animated play/pause control icon from Icons8:

The Bodymovin player library is statically hosted here and can be dropped into the HTML that way, but it is also available as a package:

npm install lottie-web ### or yarn add lottie-web

And then, in your HTML file, include the script from the dist folder in the installed package. You could also import the library as a module from Skypack:

import lottieWeb from "https://cdn.skypack.dev/lottie-web";

For now, our pause button is in a loop and it also plays automatically:

CodePen Embed Fallback

Let’s change that so the animation is triggered by an action.

Animating on a trigger

If we turn autoplay off, we get a static pause icon because that was how it was exported from After Effects.

CodePen Embed Fallback

But, worry not! Lottie provides some methods that can be applied to animation instances. That said, the documentation of the npm package is more comprehensive.

We need to do a couple things here:

  • Make it show as the “play” state initially.
  • Animate it to the “paused” state on click
  • Animate between the two on subsequent clicks.

The goToAndStop(value, isFrame) method is appropriate here. When the animation has loaded in the container, this method sets the animation to go to the provided value, then stop there. In this situation, we’d have to find the animation value when it’s at play and set it. The second parameter specifies whether the value provided is based on time or frame. It’s a boolean type and the default is false (i.e., time-based value). Since we want to set the animation to the play frame, we set it to true.

A time-based value sets the animation to a particular point in the timeline. For example, the time value at the beginning of the animation, when it’s paused, is 1. However, a frame-based value sets the animation to a particular frame value. A frame, according to TechTerms, is an individual picture in a sequence of images. So, if I set the frame value of the animation to 5, the animation goes to the fifth frame in the animation (the “sequence of images” in this situation).

CodePen Embed Fallback

After trying different values, I found out the animation plays from frame values 11 through 16. Hence, I chose 14 to be on the safe side.

Now we have to set the animation to change to pause when the user clicks it, and play when the user clicks it again. Next, we need the playSegments(segments, forceFlag) method. The segments parameter is an array type containing two numbers. The first and second numbers represent the first and last frame that the method should read, respectively. The forceFlag is a boolean that indicates whether or not the method should be fired immediately. If set to false, it will wait until the animation plays to the value specified as the first frame in the segments array before it is triggered. If true, it plays the segments immediately.

CodePen Embed Fallback

Here, I created a flag to indicate when to play the segments from play to pause, and from pause to play. I also set the forceFlag boolean to true because I want an immediate transition.

So there we have it! We rendered an animation from After Effects to the browser! Thanks Lottie!

Canvas?

I prefer to use SVG as my renderer because it supports scaling and I think it renders the sharpest animations. Canvas doesn’t render quite as nicely, and also doesn’t support scaling. However, if you want to use an existing canvas to render an animation, there are some extra things you’d have to do.

Doing more

Animation instances also have events that can also be used to configure how the animation should act.

For example, in the Pen below, I added two event listeners to the animation and set some text to be displayed when the events are fired.

CodePen Embed Fallback

All the events are available on the npm package’s docs. With that I say, go forth and render some amazing animations!

The post Animating with Lottie appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS Snapshot 2020

Css Tricks - Mon, 01/11/2021 - 6:08am

I think it’s great that the CSS Working Group does these. It’s like planting a flag in the ground saying this is what CSS looks like at this specific point in time. They do specifically say it’s not for us CSS authors though…

This document collects together into one definition all the specs that together form the current state of Cascading Style Sheets (CSS) as of 2020. The primary audience is CSS implementers, not CSS authors, as this definition includes modules by specification stability, not Web browser adoption rate.

Remember “CSS3”? That was the closest thing we had to a “snapshot” that was designed for CSS authors (and learners). Because CSS3 was so wildly successful, we saw a short round of enthusiasm for CSS4, me included. There is zero marketing panache on that snapshot page, which is exactly what CSS4 would need to succeed. Remember, HTML5 and friends (including CSS3) even had fancy logos!

If someone were to say to me “Chris, when CSS3 came around, I boned up on all that, but I haven’t kept up with CSS since, what should I learn?” I’d say “That’s a damn fine question, developer that has a normal healthy relationship with technology.” But honestly, I might struggle to answer cohesively.

I’d say: Uhm, CSS grid for sure. Custom properties. Clipping and Offset paths I suppose. prefers-reduced-motion. I dunno. There are probably like 100 things, but there is no great single reference point to see them all together.

I’ll work on putting a list together. I don’t think I’ll have the gumption to call it CSS4, but at least I’ll be able to answer that question. Feel free to suggest ideas in the comments.

The post CSS Snapshot 2020 appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Painters Tape and Fault Tolerance

Css Tricks - Fri, 01/08/2021 - 2:48pm

Snipping the top bit of Nicholas C. Zakas’s Top of the Month newsletter (go sign up!), with permission.

One of my favorite things in the world is painters tape (also called masking tape). It seems like something silly: some tape you put on a wall when you’re painting to avoid getting paint on the wall. The tape doesn’t have a strong adhesive, so it can be pulled back off the wall without damaging it. What I love about painters tape is the philosophy behind it: painting is messy, and rather than trying to avoid making a mess, painters tape allows you to make a mess initially and then clean it up easily. Even the best, most talented painter is going to splatter some paint here and there, get distracted, or otherwise end up with paint going where it shouldn’t. It’s a lot faster, easier, and less frustrating to use painters tape to cover up areas where paint is likely to go and then remove the tape to create a nice, clean, finished area. What does this have to do with software engineering?

Painters tape is all about a concept called fault tolerance. Instead of expecting everything to go well, you instead expect that there will be mistakes. When you expect there to be mistakes, you make decisions not to avoid all mistakes but rather to easily recover when a mistake occurs. Got paint where it shouldn’t be? It doesn’t matter if that spot was covered by painters tape. Forgot to put on the painters tape? Now that mistake is a bigger deal. As software engineers, we can think the same way with the code we write.

Making your code fault tolerant is about asking yourself the question: how will this fail? Not if it will fail, but assuming that it will fail, and in which ways will it fail?

The post Painters Tape and Fault Tolerance appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

`aspect-ratio` is going to deprecate FitVids

Css Tricks - Fri, 01/08/2021 - 11:23am

Jen was just tweetin’ about how the latest Safari Technical Preview has aspect-ratio. Looks like Chrome and Firefox both have it behind a flag, so with Safari joining the party, we’ll all have it soon.

I played with it a while back. It’s awesome and much needed. There are ways to make `aspect-ratio` boxes, but they largely revolve around “padding hacks.”

Dave is excited about being released from jail:

Yesssss! Soon I will be released from my Open Source prison!

Seeing it working in Edge Dev 89 (M1) as well. https://t.co/bSKrWEPQyE

— Dave Rupert (@davatron5000) January 7, 2021

Once we can rely on it, FitVids (which I use on literally every site I make in one form or another) can entirely go away in favor of a handful of CSS applied directly to the elements (usually videos-in-<iframe>s).

FitVids 2021:

CodePen Embed Fallback

The post `aspect-ratio` is going to deprecate FitVids appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Svelte and Spring Animations

Css Tricks - Fri, 01/08/2021 - 5:51am

Spring animations are a wonderful way to make UI interactions come to life. Rather than merely changing a property at a constant rate over a period of time, springs allow us to move things using spring physics, which gives the impression of a real thing moving, and can appear more natural to users.

I’ve written about spring animations previously. That post was based on React, using react-spring for the animations. This post will explore similar ideas in Svelte.

CSS devs! It’s common to think of easing when it comes to controling the feel of animations. You could think of “spring” animations as a subcategory of easing that are based on real-world physics.

Svelte actually has springs built into the framework, without needing any external libraries. We’ll rehash what was covered in the first half my previous post on react-spring. But after that, we’ll take a deep-dive into all the ways these springs can be used with Svelte, and leave the real world implementation for a future post. While that may seem disappointing, Svelte has a number of wonderful, unique features with no counterpart in React, which can be effectively integrated with these animation primitives. We’re going to spend some time talking about them.

One other note: Some of the demos sprinkled throughout may look odd because I configured the springs to be extra “bouncy” to create more obvious effect. If you the code for any of them, be sure to find a spring configuration that works for you.

Here’s a wonderful REPL Rich Harris made to show all the various spring configurations, and how they behave.

A quick primer on Svelte Stores

Before we start, let’s take a very, very quick tour of Svelte stores. While Svelte’s components are more than capable of storing and updating state, Svelte also has the concept of a store, which allows you to store state outside of a component. Since Svelte’s Spring API uses Stores, we’ll quickly introduce the salient parts here.

To create an instance of a store, we can import the writable type, and create it like so:

import { writable } from "svelte/store"; const clicks = writable(0);

The clicks variable is a store that has a value of 0. There’s two ways to set a new value of a store: the set and update methods. The former receives the value to which you’re setting the store, while the latter receives a callback, accepting the current value, and returning the new value.

function increment() { clicks.update(val => val + 1); } function setTo5() { clicks.set(5); }

State is useless if you can’t actually consume it. For this, stores offer a subscribe method, which allows you to be notified of new values — but when using it inside of a component, you can prefix the store’s name with the $ character, which tells Svelte to not only display the current value of the store, but to update when it changes. For example:

<h1>Value {$clicks}</h1> <button on:click={increment}>Increment</button> <button on:click={setTo5}>Set to 5</button>

Here’s a full, working example of this code. Stores offer a number of other features, such as derived stores, which allow you to chain stores together, readable stores, and even the ability to be notified when a store is first observed, and when it no longer has observers. But for the purposes of this post, the code shown above is all we need to worry about. Consult the Svelte docs or interactive tutorial for more info.

A crash course on springs

Let’s walk through a quick introduction of springs, and what they accomplish. We’ll take a look at a simple UI that changes a presentational aspect of some elements — opacity and transform — and then look at animating that change.

This is a minimal Svelte component that toggles the opacity of one <div>, and toggles the x-axis transform of another (without any animation).

<script> let shown = true; let moved = 0; const toggleShow = () => (shown = !shown); const toggleMove = () => (moved = moved ? 0 : 500); </script> <div style="opacity: {shown ? 1 : 0}">Content to toggle</div> <br /> <button on:click={toggleShow}>Toggle</button> <hr /> <div class="box" style="transform: translateX({moved}px)">I'm a box.</div> <br /> <button on:click={toggleMove}>Move it!</button>

These changes are applied instantly, so let’s look at animating them. This is where springs come in. In Svelte, a spring is a store that we set the desired value on, but instead of instantly changing, the store internally uses spring physics to gradually change the value. We can then bind our UI to this changing value, to get a nice animation. Let’s see it in action.

<script> import { spring } from "svelte/motion"; const fadeSpring = spring(1, { stiffness: 0.1, damping: 0.5 }); const transformSpring = spring(0, { stiffness: 0.2, damping: 0.1 }); const toggleFade = () => fadeSpring.update(val => (val ? 0 : 1)); const toggleTransform = () => transformSpring.update(val => (val ? 0 : 500)); const snapTransform = () => transformSpring.update(val => val, { hard: true }); </script> <div style="opacity: {$fadeSpring}">Content to fade</div> <br /> <button on:click={toggleFade}>Fade Toggle</button> <hr /> <div class="box" style="transform: translateX({$transformSpring}px)">I'm a box.</div> <br /> <button on:click={toggleTransform}>Move it!</button> <button on:click={snapTransform}>Snap into place</button>

We get our spring function from Svelte, and set up different spring instances for our opacity, and transform animations. The transform spring config is purposefully set up to be extra springy, to help show later how we can temporarily turn off spring animations, and instantly apply desired changes (which will come in handy later). At the end of the script block are our click handlers for setting the desired properties. Then, in the HTML, we bind our changing values directly to our elements… and that’s it! That’s all there is to basic spring animations in Svelte.

The only remaining item is the snapTransform function, where we set our transform spring to its current value, but also pass an object as the second argument, with hard: true. This has the effect of immediately applying the desired value with no animation at all.

This demo, as well as the rest of the basic examples we’ll look at in this post, is here:

Animating height

Animating height is trickier than other CSS properties, since we have to know the actual height to which we’re animating. Sadly, we can’t animate to a value of auto. That wouldn’t make sense for a spring, since the spring needs a real number so it can interpolate the correct values via spring physics. And as it happens, you can’t even animate auto height with regular CSS transitions. Fortunately, the web platform gives us a handy tool for getting the height of an element: a ResizeObserver, which enjoys pretty good support among browsers.

Let’s start with a raw height animation of an element, producing a “slide down” effect that we gradually refine in other examples. We’ll be using ResizeObserver to bind to an element’s height. I should note that Svelte does have an offsetHeight binding that can be used to more directly bind an element’s height, but it’s implemented with some <iframe> hacks that cause it to only work on elements that can receive children. This would probably be good enough for most use cases, but I’ll use a ResizeObserver because it allows some nice abstractions in the end.

First, we’ll bind an element’s height. It’ll receive the element and return a writable store that initializes a ResizeObserver, which updates the height value on change. Here’s what that looks like:

export default function syncHeight(el) { return writable(null, (set) => { if (!el) { return; } let ro = new ResizeObserver(() => el && set(el.offsetHeight)); ro.observe(el); return () => ro.disconnect(); }); }

We’re starting the store with a value of null, which we’ll interpret as “haven’t measured yet.” The second argument to writable is called by Svelte when the store becomes active, which it will be as soon as it’s used in a component. This is when we fire up the ResizeObserver and start observing the element. Then, we return a cleanup function, which Svelte calls for us when the store is no longer being used anywhere.

Let’s see this in action:

<script> import syncHeight from "../syncHeight"; import { spring } from "svelte/motion"; let el; let shown = false; let open = false; let secondParagraph = false; const heightSpring = spring(0, { stiffness: 0.1, damping: 0.3 }); $: heightStore = syncHeight(el); $: heightSpring.set(open ? $heightStore || 0 : 0); const toggleOpen = () => (open = !open); const toggleSecondParagraph = () => (secondParagraph = !secondParagraph); </script> <button on:click={ toggleOpen }>Toggle</button> <button on:click={ toggleSecondParagraph }>Toggle More</button> <div style="overflow: hidden; height: { $heightSpring }px"> <div bind:this={el}> <div>...</div> <br /> {#if secondParagraph} <div>...</div> {/if} </div> </div>

Our el variable holds the element we’re animating. We tell Svelte to set it to the DOM element via bind:this={el}. heightSpring is our spring that holds the height value of the element when it’s open, and zero when it’s closed. Our heightStore is what keeps it up to date with the element’s current height. el is initially undefined, and syncHeight returns a junk writable store that basically does nothing. As soon as el is assigned to the <div> node, that line will re-fire — thanks to the $: syntax — and get our writable store with the ResizeObserver listening.

Then, this line:

$: heightSpring.set(open ? $heightStore || 0 : 0);

…listens for changes to the open value, and also changes to the height value. In either case, it updates our spring store. We bind the height in HTML, and we’re done!

Be sure to remember to set overflow to hidden on this outer element so the contents are properly clipped as the elements toggles between its opened and closed states. Also, changes to the element’s height also animate into place, which you can see with the “Toggle More” button. You can run this in the embedded demo in the previous section.

Note that this line above:

$: heightStore = syncHeight(el);

…currently causes an error when using server-side rendering (SSR), as explained in this bug. If you’re not using SSR you don’t need to worry about it, and of course by the time you read this that bug may have been fixed. But the workaround is to merely do this:

let heightStore; $: heightStore = syncHeight(el);

…which works but is hardly ideal.

We probably don’t want the <div> to spring open on first render. Also, the opening spring effect is nice, but when closing, the effect is janky due to some content flickering. We can fix that. To prevent our initial render from animating, we can use the { hard: true } option we saw earlier. Let’s change our call to heightSpring.set to this:

$: heightSpring.set(open ? $heightStore || 0 : 0, getConfig($heightStore));

…and then see about writing a getConfig function that returns an object with the hard property that was set to true for the first render. Here’s what I came up with:

let shown = false; const getConfig = val => { let active = typeof val === "number"; let immediate = !shown && active; //once we've had a proper height registered, we can animate in the future shown = shown || active; return immediate ? { hard: true } : {}; };

Remember, our height store initially holds null and only gets a number when the ResizeObserver starts running. We capitalize on this by checking for an actual number. If we have a number, and we haven’t yet shown anything, then we know to show our content immediately, and we we do that by setting the immediate value. That value ultimately triggers the hard config value in the spring, which we saw before.

Now let’s tweak the animation to be a bit less, well, springy when we close our content. That way, things won’t flicker when they close. When we initially created our spring, we specified stiffness and damping, like so

const heightSpring = spring(0, { stiffness: 0.1, damping: 0.3 });

It turns out the spring object itself maintains those properties, which can be set anytime. Let’s update this line:

$: heightSpring.set(open ? $heightStore || 0 : 0, getConfig($heightStore));

That detects changes to the open value (and the heightStore itself) to update the spring. Let’s also update the spring’s settings based on whether we’re opening or closing. Here’s what it looks like:

$: { heightSpring.set(open ? $heightStore || 0 : 0, getConfig($heightStore)); Object.assign( heightSpring, open ? { stiffness: 0.1, damping: 0.3 } : { stiffness: 0.1, damping: 0.5 } ); }

Now when we get a new open or height value, we call heightSpring.set just like before, but we also set stiffness and damping values on the spring that are applied based on whether the element is open. If it’s closed, we set damping up to 0.5, which reduces the springiness. Of course, you’re welcome to tweak all these values and configure them as you’d like! You can see this in the “Animate Height Different Springs” section of the demo.

You might notice our code is starting to grow pretty quickly. We’ve added a lot of boilerplate to cover some of these use cases, so let’s clean things up. Specifically, we’ll make a function that creates our spring and that also exports a sync function to handle our spring config, initial render, etc.

import { spring } from "svelte/motion"; const OPEN_SPRING = { stiffness: 0.1, damping: 0.3 }; const CLOSE_SPRING = { stiffness: 0.1, damping: 0.5 }; export default function getHeightSpring() { const heightSpring = spring(0); let shown = false; const getConfig = (open, val) => { let active = typeof val === "number"; let immediate = open && !shown && active; // once we've had a proper height registered, we can animate in the future shown = shown || active; return immediate ? { hard: true } : {}; }; const sync = (open, height) => { heightSpring.set(open ? height || 0 : 0, getConfig(open, height)); Object.assign(heightSpring, open ? OPEN_SPRING : CLOSE_SPRING); }; return { sync, heightSpring }; }

There’s a lot of code here, but it’s all the code we’ve been writing so far, just packaged into a single function. Now our code to use this animation is simplified to just this

const { heightSpring, sync } = getHeightSpring(); $: heightStore = syncHeight(el); $: sync(open, $heightStore);

You can see in the “Animate Height Cleanup” section of the demo.

Some Svelte-specific tricks

Let’s pause for a moment and consider some ways Svelte differs from React, and how we might leverage that to improve what we have even further.

First, the stores we’ve been using to hold springs and change height values are, unlike React’s hooks, not tied to component rendering. They’re plain JavaScript objects that can be consumed anywhere. And, as alluded to above, we can imperatively subscribe to them so that they manually observe changing values.

Svelte also something called actions. These are functions that can be added to a DOM element. When the element is created, Svelte calls the function and passes the element as the first argument. We can also specify additional arguments for Svelte to pass, and provide an update function for Svelte to re-run when those values change. Another thing we can do is provide a cleanup function for Svelte to call when it destroys the element.

Let’s put these tools together in a single action that we can simply drop onto an element to handle all the animation we’ve been writing so far:

export default function slideAnimate(el, open) { el.parentNode.style.overflow = "hidden"; const { heightSpring, sync } = getHeightSpring(); const doUpdate = () => sync(open, el.offsetHeight); const ro = new ResizeObserver(doUpdate); const springCleanup = heightSpring.subscribe((height) => { el.parentNode.style.height = `${ height }px`; }); ro.observe(el); return { update(isOpen) { open = isOpen; doUpdate(); }, destroy() { ro.disconnect(); springCleanup(); } }; }

Our function is called with the element we want to animate, as well as the open value. We’ll set the element’s parent to have overflow: hidden. Then we use the same getHeightSpring function from before, set up our ResizeObserver, etc. The real magic is here.

const springCleanup = heightSpring.subscribe((height) => { el.parentNode.style.height = `${height}px`; });

Instead of binding our heightSpring to the DOM, we manually subscribe to changes, then set the height ourselves, manually. We wouldn’t normally do manual DOM updates when using a JavaScript framework like Svelte but, in this case, it’s for a helper library, which is just fine in my opinion.

In the object we’re returning, we define an update function which Svelte will call when the open value changes. We update the original argument to this function, which the function closes over ( i.e. creates a closure around) and then calls our update function to sync everything. Svelte calls the destroy function when our DOM node is destroyed.

Best of all, using this action is a snap:

<div use:slideAnimate={open}>

That’s it. When open changes, Svelte calls our update function.

Before we move on, let’s make one other tweak. Notice how we remove the springiness by changing the spring config when we collapse the pane with the “Toggle” button; however, when we make the element smaller by clicking the “Toggle More” button, it shrinks with the usual springiness. I dislike that, and prefer shrinking sizes move with the same physics we’re using for collapsing.

Let’s start by removing this line in the getHeightSpring function:

Object.assign(heightSpring, open ? OPEN_SPRING : CLOSE_SPRING);

That line is inside the sync function that getHeightSpring created, which updates our spring settings on every change, based on the open value. With it gone, we can start our spring with the “open” spring config:

const heightSpring = spring(0, OPEN_SPRING);

Now let’s change our spring settings when either the height of our content changes, or when the open value changes. We already have the ability to observe both of those things changing — our ResizeObserver callback fires when the size of the content changes, and the update function of our action fires whenever open changes.

Our ResizeObserver callback can be changed, like this:

let currentHeight = null; const ro = new ResizeObserver(() => { const newHeight = el.offsetHeight; const bigger = newHeight > currentHeight; if (typeof currentHeight === "number") { Object.assign(heightSpring, bigger ? OPEN_SPRING : CLOSE_SPRING); } currentHeight = newHeight; doUpdate(); });

currentHeight holds the current value, and we check it on size changes to see which direction we’re moving. Next up is the update function. Here’s what it looks like after our change:

update(isOpen) { open = isOpen; Object.assign(heightSpring, open ? OPEN_SPRING : CLOSE_SPRING); doUpdate(); },

Same idea, but now we’re only checking whether open is true or false. You can see these iterations in the “Slide Animate” and “Slide Animate 2” sections of the demo.

Transitions

We’ve talked about animating items already on the page so far, but what about animating an object when it first renders? And when it un-mounts? That’s called a transition, and it’s built into Svelte. The docs do a superb job covering the common use cases, but there’s one thing that’s not yet (directly) supported: spring-based transitions.

/explanation Note that what Svelte calls a “transition” and what CSS calls a “transition” are very different things. CSS means transitioning one value to another. Svelte is referring to elements as they “transition” into and out of the DOM entirely (something that CSS doesn’t help with much at all).

To be clear, the work we’re doing here is made for adding spring-based animations into Svelte’s transitions. This is not currently supported, so it requires some tricks and workarounds that we’ll get into. If you don’t care about using springs, then Svelte’s built-in transitions can be used, which are significantly simpler. Again, check the docs for more info.

The way transitions work in Svelte is that we provide a duration in milliseconds (ms) along with an optional easing function, then Svelte provides us a callback with a value running from 0 to 1, representing how far along the transition is, and we turn that into whatever CSS we want. For example:

const animateIn = () => { return { duration: 2000, css: t => `transform: translateY(${t * 50 - 50}px)` }; };

…is used like this:

<div in:animateIn out:animateOut class="box"> Hello World! </div>

When that <div> first mounts, Svelte:

  • calls our animateIn function,
  • rapidly calls the CSS function on our resulting object ahead of time with values from 0 to 1,
  • collects our changing CSS result, then
  • compiles those results into a CSS keyframes animation, which it then applies to the incoming <div>.

This means that our animation will run as a CSS animation — not as JavaScript on the main thread — offering a nice performance boost for free.

The variable t starts at 0, which results in a translation of -50px. As t gets closer to 1, the translation approaches 0, its final value. The out transition is about the same, but in reverse, with the added feature of detecting the box’s current translation value, starting from there. So, if we add it then quickly remove it, the box will start to leave from its current position rather than jumping ahead. However, if we then re-add it while it’s leaving, it will jump, something we’ll talk about in just moment.

You can run this in the “Basic Transition” section of the demo.

Transitions, but with springs

While there’s a number of easing functions that alter the flow of an animation, there’s no ability to directly use springs. But what we could do is find some way to run a spring ahead of time, collect the resulting values, and then, when our css function is called with the a t value running from 0 to 1, look up the right spring value. So, if t is 0, we obviously need the first value from thespring. When t is 0.5, we want the value right in the middle, and so on. We also need a duration, which is number_of_spring_values * 1000 / 60 since there’s 60 frames per second.

We won’t write that code here. Instead, we’ll use the solution that already exists in the svelte-helpers library, a project I started. I grabbed one small function from the Svelte codebase, spring_tick, then wrote a separate function to repeatedly call it until it’s finished, collecting the values along the way. That, along with a translation from t to the correct element in that array (or a weighted average if there’s not a direct match), is all we need. Rich Harris gave a helping hand on the latter, for which I’m grateful.

Animate in

Let’s pretend a big red <div> is a modal that we want to animate in, and out. Here’s what an animateIn function looks like:

import { springIn, springOut } from "svelte-helpers/animation"; const SPRING_IN = { stiffness: 0.1, damping: 0.1 }; const animateIn = node => { const { duration, tickToValue } = springIn(-80, 0, SPRING_IN); return { duration, css: t => `transform: translateY(${ tickToValue(t) }px)` }; };

We feed the values we want to spring to, as well as our spring config to the springIn function. That gives us a duration, and a function for translating the current tickToValue into the current value to apply in the CSS. That’s it!

Animate out

Closing the modal is the same thing, with one small tweak

const SPRING_OUT = { stiffness: 0.1, damping: 0.5, precision: 3 }; const animateOut = node => { const current = currentYTranslation(node); const { duration, tickToValue } = springOut(current ? current : 0, 80, SPRING_OUT); return { duration: duration, css: t => `transform: translateY(${ tickToValue(t) }px)` }; };

Here, we’re check the modal’s current translation position, then use that as a starting point for the animation. This way, if the user opens and then quickly closes the modal, it’ll exit from its current position, rather than teleporting to 0, and then leaving. This works because the animateOut function is called when the element un-mounts, at which point we generate the object with the duration property and css function so the animation can be computed.

Sadly, it seems re-mounting the object while it’s in the process of leaving does not work, at least well. The animateIn function is not called de novo, but rather the original animation is re-used, which means it’ll always start at -80. Fortunately this almost certainly would not matter for a typical modal component, since a modal is usually removed by clicking on something, like the background overlay, meaning we are unable to re-show it until that overlay has finished animating out. Besides, repeatedly adding and removing an element with bidirectional transitions might make for a fun demo, but they’re not really common in practice, at least in my experience.

One last quick note on the outgoing spring config: You may have noticed that I set the precision ridiculously high (3 when the default is 0.01). This tells Svelte how close to get to the target value before deciding it is “done.” If you leave the default at 0.01, the modal will (almost) hit its destination, then spend quite a few milliseconds imperceptibly getting closer and closer before deciding it’s done, then remove itself from the DOM. This gives the impression that the modal is stuck, or otherwise delayed. Moving the precision to a value of 3 fixes this. Now the modal animates to where it should go (or close enough), then quickly goes away.

More animation

Let’s add one final tweak to our modal example. Let’s have it fade in and out while animating. We can’t use springs for this, since, again, we need to have one canonical duration for the transition, and our motion spring is already providing that. But spring animations usually make sense for items actually moving, and not much else. So let’s use an easing function to create a fade animation.

If you need help picking the right easing function, be sure to check out this handy visualization from the Svelte docs. I’ll be using the quintOut and quadIn functions.

import { quintOut, quadIn } from "svelte/easing";

Our new animateIn function looks pretty similar. Our css function does what it did before, but also runs the tickToValue value through the quintOut easing function to get our opacity value. Since t runs from 0 to 1 during an in transition, and 1 to 0 during an out transition, we don’t have to do anything further to it before applying to opacity.

const SPRING_IN = { stiffness: 0.1, damping: 0.1 }; const animateIn = node =>; { const { duration, tickToValue } = springIn(-80, 0, SPRING_IN); return { duration, css: t => { const transform = tickToValue(t); const opacity = quintOut(t); return `transform: translateY(${ transform }px); opacity: ${ opacity };`; } }; };

Our animateOut function is similar, except we want to grab the element’s current opacity value, and force the animation to start there. So, if the element is in the process of fading in, with an opacity of, say, 0.3, we don’t want to reset it to 1, and then fade it out. Instead, we want to fade it out from 0.3.

Multiplying that starting opacity by whatever value the easing function returns accomplishes this. If our t value starts at 1, then 1 * 0.3 is 0.3. If t is 0.95, we do 0.95 * 0.3 to get a value, which is a little less than 0.3, and so on.

Here’s the function:

const animateOut = node => { const currentT = currentYTranslation(node); const startOpacity = +getComputedStyle(node).opacity; const { duration, tickToValue } = springOut( currentT ? currentT : 0, 80, SPRING_OUT ); return { duration, css: t => { const transform = tickToValue(t); const opacity = quadIn(t); return `transform: translateY(${ transform }px); opacity: ${ startOpacity * opacity }`; } }; };

You can run this example in the demo with the “Spring Transition With Fade component.

Parting thoughts

Svelte is a lot of fun! In my (admittedly limited) experience, it tends to provide extremely simple primitives, and then leaves you to code up whatever you need. I hope this post has helped explain how the spring animations can be put to good use in your web applications.

And, hey, just a quick reminder to consider accessibility when working with springs, just as you would do with any other animation. Pairing these techniques with something like prefers-reduced-motion can ensure that only folks who prefer animations are the ones who get them.

The post Svelte and Spring Animations appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Creating CSS APIs without JavaScript With the datasette-css-properties plugin

Css Tricks - Thu, 01/07/2021 - 1:37pm

Simon Willison has a project called Datasette, an open source multi-tool for exploring and publishing data. I’m not sure I’m qualified to explain it, but it’s like a tool to make handling data easier and doing more — through the web — with data you have. Like making that data queryable and giving it an API.

I would think, typically, you’d get the results of an API call against your data in something useful, like JSON. But Simon made a plugin that outputs the results as CSS custom properties instead, and blogged it:

It’s very, very weird—it adds a .css output extension to Datasette which outputs the result of a SQL query using CSS custom property format. This means you can display the results of database queries using pure CSS and HTML, no JavaScript required!

Here’s what I said just recently in “Custom Properties as State”:

This makes me think that a CDN-hosted CSS file like this could have other useful stuff, like today’s date for usage in pseudo content, or other special time-sensitive stuff. Maybe the phase of the moon? Sports scores?! Soup of the day?!

And Simon is like, how about roadside attractions?

CodePen Embed Fallback

My brain automatically worries about the accessibility of that, but… aren’t pseudo-elements fairly and reliably read in screen readers these days? You still can’t select the text though, or find-on-page, which are both usability and accessibility issues, so don’t consider this like a real thing that you really do for production work with unknown users.

His blog post demonstrates a slightly more dynamic example where the time of day outputs a different color. That makes me think of @property and declaring types for custom properties. I think this gets a smidge more useful when you can use the values that come back as specific syntaxes.

The post Creating CSS APIs without JavaScript With the datasette-css-properties plugin appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Win a Copy of Zell Liew’s Learn JavaScript Course

Css Tricks - Thu, 01/07/2021 - 5:48am

Zell Liew is giving away 10 free copies of his Learn JavaScript course, and entering the giveaway is pretty easy: sign up for his newsletter. I’ve personally subscribed for some time now and all I get is as occasional hand-written email with useful JavaScript gems. It’s sort of like winning no matter if you get the course or not.

If you jump down to the lesson plan, you’ll see that the course is chock-full of material, so this is no cheapie. There’s something like 300 lessons in there. Plus, Zell is a master at explaining incredibly complex things in a way that’s accessible to anyone, whether you’re getting started or looking to brush up your skills. Believe me, I’ve edited his work and I learn something from it every time.

That’s the spiel! Enter before Wednesday, January 13, to throw your hat in the ring.

Direct Link to ArticlePermalink

The post Win a Copy of Zell Liew’s Learn JavaScript Course appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Styling Code In and Out of Blocks

Css Tricks - Wed, 01/06/2021 - 11:31am

We’ll get to that, but first, a long-winded introduction.

I’m still not in a confident place knowing a good time to use native web components. The templating isn’t particularly robust, so that doesn’t draw me in. There is no state management, and I like having standard ways of handling that. If I’m using another library for components anyway, seems like I would just stick with that. So, at the moment, my checklist is something like:

  • Not using any other JavaScript framework that has components
  • Templating needs aren’t particularly complex
  • Don’t need particularly performant re-rendering
  • Don’t need state management

I’m sure there is tooling that helps with these things and more (the devMode episode with some folks from Stencil was good), but if I’m going to get into tooling-land, I’d be extra tempted to go with a framework, and probably not framework plus another thing with a lot of overlap.

The reasons I am tempted to go with native web components are:

  • They are native. No downloads of frameworks.
  • The Shadow DOM is a true encapsulation in a way a framework can’t really do.
  • I get to build my own HTML element that I use in HTML, with my own API design.

It sorta seems like the sweet spot for native web components is design system components. You build out your own little API for the components in your system, and people can use them in a way that is a lot safer than just copy and paste this chunk of HTML. And I suppose if consumers of the system wanted to BYO framework, they could.

So you can use like <our-tabs active-tab="3"> rather than <div class="tabs"> ... <a href="#3" class="tab-is-active">. Refactoring the components certainly gets a lot easier as changes percolate everywhere.

I’ve used them here on CSS-Tricks for our <circle-text> component. It takes the radius as a parameter and the content via, uh, content, and outputs an <svg> that does the trick. It gave us a nice API for authoring that abstracted away the complexity.

So!

It occurred to me a “code block” might be a nice use-case for a web component.

  • The API would be nice for it, as you could have attributes control useful things, and the code itself as the content (which is a great fallback).
  • It doesn’t really need state.
  • Syntax highlighting is a big gnarly block of CSS, so it would be kinda cool to isolate that away in the Shadow DOM.
  • It could have useful functionality like a “click to copy” button that people might enjoy having.

Altogether, it might feel like a yeah, I could use this kinda component.

This probably isn’t really production ready (for one thing, it’s not on npm or anything yet), but here’s where I am so far:

CodePen Embed Fallback

Here’s a thought dump!

  • What do you do when a component depends on a third-party lib? The syntax highlighting here is done with Prism.js. To make it more isolated, I suppose you could copy and paste the whole lib in there somewhere, but that seems silly. Maybe you just document it?
  • Styling web components doesn’t feel like it has a great story yet, despite the fact that Shadow DOM is cool and useful.
  • Yanking in pre-formatted text to use in a template is super weird. I’m sure it’s possible to do without needing a <pre> tag inside the custom element, but it’s clearly much easier if you grab the content from the <pre>. Makes the API here just a smidge less friendly (because I’d prefer to use the <code-block> alone).
  • I wonder what a good practice is for passing along attributes that another library needs. Like is data-lang="CSS" OK to use (feels nicer), and then convert it to class="language-css" in the template because that’s what Prism wants? Or is it better practice to just pass along attributes as they are? (I went with the latter.)
  • People complain that there aren’t really “lifecycle methods” in native web components, but at least you have one: when the thing renders: connectedCallback. So, I suppose you should do all the manipulation of HTML and such before you do that final shadowRoot.appendChild(node);. I’m not doing that here, and instead am running Prism over the whole shadowRoot after it’s been appended. Just seemed to work that way. I imagine it’s probably better, and possible, to do it ahead of time rather than allow all the repainting caused by injecting spans and such.
  • The whole point of this is a nice API. Seems to me thing would be nicer if it was possible to drop un-escaped HTML in there to highlight and it could escape it for you. But that makes the fallback actually render that HTML which could be bad (or even theoretically insecure). What’s a good story for that? Maybe put the HTML in HTML comments and test if <!-- is the start of the content and handle that as a special situation?

Anyway, if you wanna fork it or do anything fancier with it, lemme know. Maybe we can eventually put it on npm or whatever. We’ll have to see how useful people think it could be.

The post Styling Code In and Out of Blocks appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Whack-a-Mole: The CSS Edition

Css Tricks - Wed, 01/06/2021 - 5:39am

We’ve seen the checkbox hack and how it can be used to build a complete state machine in CSS. Today, we’ll take that line of thought a step further and build a simple game of Whack-A-Mole, where the player needs to react quickly to win … all without a touch of JavaScript.

This might seem a little silly in a language that doesn’t have any notion of timers or intervals, but the secret is that CSS does — it’s just packaged in a little feature called CSS Animations.

Take a look at this double-click handler. Note that CSS doesn’t know what a click is, much less a double click:

CodePen Embed Fallback

How does it work? Here’s a recording of the important elements, recolored and slowed down:

The idea is that when you click on the button for the first time, it moves the double-click element in place under the cursor, but it also causes a masking element to start moving up to cover it.

  • If the second click comes quickly enough after the first (as on the left side of the recording), it happens on the double-click (blue) element.
  • Otherwise (as on the right side of the recording), it happens on the masking (yellow) element, which has the effect of a single-click element.

(For an in-depth explanation, take a look at my write-up on the pure-CSS double-click handler here.)

There are two ideas in play here:

  1. Animations can be used to manage states according to a set pattern. (I’m using the term “state” loosely.)
  2. By changing an element’s position, we can change whether or not an user is allowed to take an action.

That’s all we need!

Now, instead of having our target scroll into view, we could instead use animation-timing-function: step-end to have it pop in and out, sort of like a mole in a hole:

CodePen Embed Fallback

I tried a few different options for moving the mole out of the way, and changing its absolute position — here left — seems to work the best. Using a translation would be convenient, but unfortunately leaves Firefox thinking the cursor is on the wrong element because changing transform in the Gecko layout engine doesn’t trigger a re-layout. (Normally, this would be a good thing for performance reasons, but not so much for our little demo!)

With a bit of styling, we can make it look more like a game element:

CodePen Embed Fallback

The “mole” here is basically a restyled CSS label that triggers the checkbox hack. So is the hole. When the mole’s animation takes it over the hole, clicking in the region triggers the mole’s radio input; when the mole is out of the way, clicking triggers the hole’s radio input.

The next step is to put a couple of holes next to each other and have the moles bounce around among them, each on a different negative animation-delay. With a state machine reading off which of the moles have been hit and which of the holes have been collapsed, it turns into a neat little game.

I used short Python scripts to generate both the state machine selectors and the mole keyframes. It gets a bit unwieldy for hand-coding otherwise. This is mostly because CSS also has no concept of random numbers, which leaves us no choice but to hardcode the “random” mole behavior.

CodePen Embed Fallback

There we have it: a complete reaction-based game, entirely in HTML and CSS.

The post Whack-a-Mole: The CSS Edition appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Some Recent Videos About Websites That Are Pretty Good

Css Tricks - Tue, 01/05/2021 - 12:42pm

Here’s a little hodgepodge of videos I’ve recently bookmarked (and watched). I couldn’t decide if each one of them should be a separate blog post or if I should do this combined list post thing. If I had a lot more to say about each video I would have split them off, but I went with the combined post and fewer words here. Let me know in the comments if you have a preference on that kind of thing.

Here’s Tom Scott explaining why the web is such a mess

Cookies. It all cookies fault. Kinda. Also humans.

This is the same Tom that did that super neat video that updated it’s own title with the view count.

I don’t know this person’s name but I appreciated how it gets the details right in this recreation of the Discord sidebar

Except the fact that the :hover was on the <li> itself rather than a link that went somewhere sensible, but hey, I guess it’s slightly better than the actual Discord markup where it’s <div class="listItem_">.

Heydon gets all weird about progressive enhancment

I can’t embed it here because, even though it looks like Heydon switched over to Vimeo rather than just straight up <video> tags, the privacy settings have it locked to briefs.video only.

I liked the point about “the basic layout is not a broken layout,” except, doesn’t it seem like in that exact case it wouldn’t matter if you wrapped the grid-template-rows in a @supports or not? I love that @supports is a thing, and even more so now that we’ve passed the awkward years where @supports itself didn’t have full browser support, but I don’t find myself reaching for it that much, as it’s only really useful if you need to do something different than “just let it not work,” which I don’t find terribly common.

Houssein Djirdeh and Jason Miller get into “modern JavaScript”

We’ve gotta be so careful about compiled code. There is an example where one line of JavaScript gets compiled into 7000 bytes, which is bigger and far slower than intended. Taking care of older browsers when you have a significant number of users using that old browser is a really great thing, but you might be surprised at the browser support of “modern JavaScript” and find you are compiling more than you need to.

The kicker is that you only really control what you write, but probably most of what you ship is third-party. That means npm, which is absolutely loaded with very non-modern JavaScript. The sweet spot, they say, is calling ES 2017 the compile target in general. If you need even older support, use the ol’ differential serving trick.

There’s a blog version of this video, too.

Jessica Chan challenges William Candillon to a CSSBattle

Like literally CSSBattle, the website.

They go back and forth trying to figure out how to make this little spiky virus-looking thing. I totally relate to their approaches! Neither of them are like amazingly clever with either the HTML or CSS — they just try to get it done. That’s why I could never get into CSSBattle myself. I appreciate people’s trickery (duh), but my actual CSS writing style is almost like verbose-on-purpose.

The post Some Recent Videos About Websites That Are Pretty Good appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Custom Properties as State

Css Tricks - Tue, 01/05/2021 - 6:05am

Here’s a fun idea from James Stanley: a CSS file (that presumably updates daily) containing CSS custom properties for “seasonal” colors (e.g. spring is greens, fall is oranges). You’d then use the values to theme your site, knowing that those colors change slightly from day to day.

This is what I got while writing this:

:root { --seasonal-bg: hsl(-68.70967741935485,9.419354838709678%,96%); --seasonal-bgdark: hsl(-68.70967741935485,9.419354838709678%,90%); --seasonal-fg: hsl(-68.70967741935485,9.419354838709678%,30%); --seasonal-hl: hsl(-83.70967741935485,30.000000000000004%,50%); --seasonal-hldark: hsl(-83.70967741935485,30.000000000000004%,35%); }

I think it would be more fun if the CSS file provided was just the custom properties and not the opinionated other styles (like what sets the body background and such). That way you could implement the colors any way you choose without any side effects.

CSS as an API?

This makes me think that a CDN-hosted CSS file like this could have other useful stuff, like today’s date for usage in pseudo content, or other special time-sensitive stuff. Maybe the phase of the moon? Sports scores?! Soup of the day?!

/* <div class="soup">The soup of the day is: </div> */ .soup::after { content: var(--soupOfTheDay); /* lol kinda */ }

It’s almost like a data API that is tremendously easy to use. Pseudo content is even accessible content these days — but you can’t select the text of pseudo-elements, so don’t read this as an actual endorsement of using CSS as a content API.

Custom Property Flexibility

Will Boyd just blogged about what is possible to put in a custom property. They are tremendously flexible. Just about anything is a valid custom property value and then the usage tends to behave just how you think it will.

body { /* totally fine */ --rgba: rgba(255, 0, 0, 0.1); background: var(--rgba); /* totally fine */ --rgba: 255, 0, 0, 0.1; background: rgba(var(--rgba)); /* totally fine */ --rgb: 255 0 0; --a: 0.1; background: rgb(var(--rgb) / var(--a)); } body::after { /* totally fine */ --song: "I need quotes to be pseudo content \A and can't have line breaks without this weird hack \A but still fairly permissive (&#x1f4a7;&#x1f4a7;&#x1f4a7;) "; content: var(--song); white-space: pre; }

Bram Van Damme latched onto that flexiblity while covering Will’s article:

That’s why you can use CSS Custom Properties to:

perform conditional calculations

pass data from within your CSS to your JavaScript

inject skin tone / hair color modifiers onto Emoji 

toggle multiple values with one custom property (--foo: ; hack)

Bram points out this “basic” state-flipping quality that a custom property can pull off:

:root { --is-big: 0; } .is-big { --is-big: 1; } .block { padding: calc( 25px * var(--is-big) + 10px * (1 - var(--is-big)) ); border-width: calc( 3px * var(--is-big) + 1px * (1 - var(--is-big)) ); }

Add a couple of scoops of complexity and you get The Raven (media queries with custom properties).

I’d absolutely love to see something happen in CSS to make this easier. Using CSS custom properties for generic state would be amazing. We could apply arbitrary styles when the UI is in arbitrary states! Think of how useful media queries are now, or that container queries will be, but compounded because it’s arbitrary state, not just state that those things expose.

Bram covered that as well, mentioning what Lea Verou called “higher level custom properties”:

/* Theoretical! */ .square { width: 2vw; padding: 0.25vw; aspect-ratio: 1/1; @if (var(--size) = big) { width: 16vw; padding: 1vw; } } .my-input { @if(var(--pill) = on) { border-radius: 999px; } } About that naming

Will calls them “CSS variables” which is super common and understandable. You’ll read (and I have written) sentences often that are like “CSS variables (a.k.a CSS Custom Properties)” or “CSS Custom Properties (a.k.a CSS Variables.” Šime Vidas recently noted there is a rather correct way to refer to these things: --this-part is the custom property and var(--this-part) is the variable, which comes right from usage in the spec.

JavaScript Library State… Automatically?

I’m reminded of this Vue proposal. I’m not sure if it went anywhere, but the idea is that the state of a component would automatically be exposed as CSS custom properties.

<template> <div class="text">Hello</div> </template> <script> export default { data() { return { color: 'red' } } } </script> <style vars="{ color }"> .text { color: var(--color); } </style>

By virtue of having color as part of the state of this component, then --color is available as state to the CSS of this component. I think that’s a great idea.

What if every time you used useState in React, CSS custom properties were put on the :root and were updated automatically. For example, if you did this:

import React, { useState } from 'https://cdn.skypack.dev/react@^16.13.1'; import ReactDOM from 'https://cdn.skypack.dev/react-dom@^16.13.1'; const App = () => { const [ activeColor, setActiveColor ] = useState("red"); return( <div className="box"> <h1>Active Color: {activeColor}</h1> <button onClick={() => {setActiveColor("red")}}>red</button> <button onClick={() => {setActiveColor("blue")}}>blue</button> </div> ); } ReactDOM.render(<App />, document.getElementById("root"))

And you knew you could do like:

.box { border-color: 2px solid var(--activeColor); }

Because the state automatically mapped itself to a custom property. Someone should make a useStateWithCustomProperties hook or something to do that. #freeidea

Libraries like React and Vue are for building UI. I think it makes a lot of sense that the state that they manage is automatically exposed to CSS.

Could browsers give us more page state as environment variables?

Speaking of state that CSS should know about, I’ve seen quite a few demos that do fun stuff by mapping over things, like the current mouse position or scroll position, over to CSS. I don’t think it’s entirely unreasonable to ask for that data to be natively exposed to CSS. We already have the concept of environment variables, like env(safe-area-inset-top), and I could see that being used to expose page state, like env(page-scroll-percentage) or env(mouseY).

The post Custom Properties as State appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

The End of Adobe Flash

Css Tricks - Mon, 01/04/2021 - 10:33am

I come to bury Flash, not to praise it, writes Matt May in this excellent thread about the end of Adobe Flash. Not so long ago, web designers used Flash to create striking visuals and animations and games. But shortly after that, it began to replace HTML and CSS which caused a ton of accessibility problems. Most Flash websites weren’t navigable by keyboard and screen readers couldn’t parse them at all.

Matt describes this core problem at the very heart of Flash: the fact that it excluded so many people from the web back then.

The biggest joke of the 2000s around Flash was that it was a tool for making restaurant menus. Flash devs made apps that looked the way restaurateurs wanted them, and sold them in bulk. But how they did it was by faking buttons, scroll bars, etc. It was a picture of an interface.

— Matt May (@mattmay) December 31, 2020

“A picture of an interface” is a good way to think about it. But, overall, I reckon this thread is important because it reinforces the idea that we ought to think about accessibility every single day, regardless of whether we’re working on a large web app, a tiny marketing website, or contributing to an enormous JavaScript framework:

Finally: if you make the platform, you have an immense responsibility to the people who build on it, and the people who use it. In a very real way, you set the upper limit on how many people get to participate equitably within your ecosystem. NEVER, EVER forget this fact.

— Matt May (@mattmay) December 31, 2020

Every day we write code, we’re deciding who is welcome and who is not.

Direct Link to ArticlePermalink

The post The End of Adobe Flash appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Make Your Own Tools

Css Tricks - Mon, 01/04/2021 - 4:59am

Spencer Miskoviak on the Wealthfront blog:

By creating custom DevTools specific to an app, they can operate at an even higher abstraction to handle things like user interactions, or debugging tracking events. While this requires building and maintaining the custom DevTools, it also means it can be tailored to the needs of the app and engineers to streamline development.

I think it’s super cool and smart to build custom tools for your team of developers. Even if custom tools are just for yourself they can be a productivity boon. But by building custom tools for your whole team, and opening the door to their ideas, that’s extra smart and compounds the value.

Spencer showcased a variety of different tools they have, all under the umbrellas of a UI popup widget thingy:

  • Shows current branch and CI status
  • Fills out forms, performs user actions, switches between users
  • Highlights components

Clever stuff.

We don’t have a fancy UI widget like that at CodePen, but do have some productivity-helping fuctionality sprinkled into the app. For example, many forms have a prefill button that only shows up for devs:

And we have a custom tool for our support inbox that gives context to the users and content that the support ticket references:

Not to mention a whole protected admin area on the site itself to perform a whole slew of admin and developer focused tasks:

I think the “component highlighter” that Spencer talked about is particularly neat:

React DevTools can be helpful in seeing what parts of the current page are which components, but that’s not on-page like this. I think it would be rad to have a little &#x1f517; next to each title that would open that file in VS Code.

Speaking of building your own tools, Shawn Wang wrote “You’re Allowed To Make Your Own Tools” recently:

Even the greatest software has parts that aren’t so great for you. But the difference between you and everyone else is that you can code.

Shawn talks about things like…

  • Building your own custom stylesheets
  • Building a UI query generator
  • Building your own CLIs (I’m reminded of Mina Markham’s dotfiles)
  • Building your own proxies

Shawn wrote his own dang proxy for Google Search Results to optimize them and present them how he likes:

Once in a while, I’m in the mood to focus on tooling, which leads me to do stuff like when I decided to “Run Gulp as You Open a VS Code Project using VS Code Tasks” which I had to learn all about and struggle through weird problems. I’d think a great DevOps person at a company would be all over stuff like this—constantly thinking of developer experience for their own people.

I even scripted the opening of a text-based multi-player video game I play not long ago to save myself some time.

And speaking of building your own tools generally, I think of Dick Proenneke’s in Alone in the Wilderness documentary. In this intro clip, you can hear Dick talk about quite literally building tools, which was useful for him as he didn’t need to hand-haul them deep into the Alaskan wilderness.

&#x1f6e0;

The post Make Your Own Tools appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Syndicate content
©2003 - Present Akamai Design & Development.