Web Standards

On fixed elements and backgrounds

Css Tricks - Wed, 06/03/2020 - 5:04am

After just playing with apsect-ratio and being pleasantly surprised at how intuitive it is, here’s an example of CSS acting unintuitively:

If you have a fixed element on your page, which means it doesn’t move when you scroll, you might realise that it no longer acts fixed if you apply a CSS filter on its nearest ancestor. Go ahead, try it on the CodePen.

This is because applying a filter on the fixed element’s immediate parent makes it becoming the containing block instead of the viewport.

Hui Jing has more to teach in there about scrolling, rendering performance, and trickery with using pseudo elements to avoid issues.

I find this kind of thing among the most challenging CSS concepts to wrap my mind around, like Block Formatting Contexts (BFCs). A BFC Is A Mini Layout In Your Layout. 🤯

Direct Link to ArticlePermalink

The post On fixed elements and backgrounds appeared first on CSS-Tricks.

Behind the Source: Cassie Evans

Css Tricks - Tue, 06/02/2020 - 1:37pm

I feel like the tech industry takes itself far too seriously sometimes. I get frustrated by all the posturing and gatekeeping – “You’re not a real developer unless you use x framework”, “CSS isn’t a real programming language”.

I think this kind of rhetoric often puts new developers off, and the ones that don’t get put off are more inclined to skip over learning things like semantic markup and accessibility in favour of learning the latest framework.

Having a deeper knowledge of HTML and CSS is often devalued.

Posturing and gatekeeping, indeed. I’ve yet to witness a conversation where discussing what is or isn’t “real” programming was fruitful for anybody.

Related sentiment from Mehdi Zed about PHP:

Most developers who hate PHP hate it out of elitism or ignorance. Either way it’s dumb.

Direct Link to ArticlePermalink

The post Behind the Source: Cassie Evans appeared first on CSS-Tricks.

Chrome 83 Form Element Styles

Css Tricks - Tue, 06/02/2020 - 1:33pm

There have been some aesthetic changes to what form elements look like as of Chrome 83. Anything with gradient colorization is gone (notably the extra-shiny <meter> stuff). The consistency across the board is nice, particularly between inputs and textareas. Not a big fan of the new <select> styling, but I hear a lot of accessibility research went into this, so it’s hard to complain there — plus you can always change it.

Hakim has a nice comparison tweet:

Chrome’s new default form styles are out &#x1f440; pic.twitter.com/Pr6qi1LpPn

— Hakim El Hattab (@hakimel) May 26, 2020 The Jetpack plugin for WordPress has a new comparison block and I’m going to try it out here. You can swipe between the items, just for fun (drag the slider in the middle).

This is not accompanied by new standardized ways to change the look of form elements with CSS, although browsers are well aware of that and seem to draw nearer and nearer all the time. I believe this was a step along that path.

I also see there is a new <input type="time"> as well. The old version looked like this and offered no UI controls:

Now we get this beast with controls:

There are no visual indicators or buttons, but you can scroll those columns.

Reddit notes that it uses the same pseudo element that date pickers use, so if you want it gone, you can scope it to these types of inputs (or not) and remove it.

input[type="time"]::-webkit-calendar-picker-indicator { display: none; }

I’d call it an improvement (I like UI controls for things), but it does continue to highlight the need to be able to style these things, particularly if the goal is to have people actually use them and not (poorly) rebuild them.

The post Chrome 83 Form Element Styles appeared first on CSS-Tricks.

A New Way to Delay Keyframes Animations

Css Tricks - Tue, 06/02/2020 - 4:45am

If you’ve ever wanted to add a pause between each iteration of your CSS @keyframes animation, you’ve probably been frustrated to find there’s no built-in way to do it in CSS. Sure, we can delay the start of a set of @keyframes with animation-delay, but there’s no way to add time between the first iteration through the keyframes and each subsequent run. 

This came up when I wanted to adapt this shooting stars animation for use as the background of the homepage banner in a space-themed employee portal. I wanted to use fewer stars to reduce distraction from the main content, keep CPUs from melting, and still have the shooting stars seem random.

No pausing

For comparisons sake.

CodePen Embed Fallback The “original” delay method

Here’s an example of where I applied the traditional keyframes delay technique to my fork of the shooting stars.

CodePen Embed Fallback

This approach involves figuring out how long we want the delay between iterations to be, and then compressing the keyframes to a fraction of 100%. Then, we maintain the final state of the animation until it reaches 100% to achieve the pause.

@keyframes my-animation { /* Animation happens between 0% and 50% */ 0% { width: 0; } 15% { width: 100px; } /* Animation is paused/delayed between 50% and 100% */ 50%, 100% { width: 0; } }

I experienced the main drawback of this approach: each keyframe has to be manually tweaked, which is mildly painful and certainly prone to error. It’s also harder to understand what the animation is doing if it requires mentally transposing all the keyframes back up to 100%.

New technique: hide during the delay

Another technique is to create a new set of @keyframes that is responsible for hiding the animation during the delay. Then, apply that with the original animation, at the same time.

.target-of-animation { animation: my-awesome-beboop 1s, pause-between-iterations 4s; } @keyframes my-awesome-beboop { ... } @keyframes pause-between-iterations { /* Other animation is visible for 25% of the time */ 0% { opacity: 1; } 25% { opacity: 1; } /* Other animation is hidden for 75% of the time */ 25.1% { opacity: 0; } 100% { opacity: 0; } }

A limitation of this technique is that the pause between animations must be an integer multiple of the “paused” keyframes. That’s because keyframes that repeat infinitely will immediately execute again, even if there are longer running keyframes being applied to the same element.

Interesting aside: When I started this article, I mistakenly thought that an easing function is applied at 0% and ends at 100%.. Turns out that the easing function is applied to each CSS property, starting at the first keyframe where a value is defined and ending at the next keyframe where a value is defined (e.g., an easing curve would be applied from 25% to 75%, if the keyframes were 25% { left: 0 } 75% { left: 50px}). In retrospect, this totally makes sense because it would be hard to adjust your animation if it was a subset of the total easing curve, but my mind is slightly blown.

In the my-awesome-beboop keyframes example above, my-awesome-beboop will run three times behind the scenes during the pause-between-animations keyframes before being revealed for what appears to be its second loop to the user (which is really the fifth time it’s been executed).  

Here’s an example that uses this to add a delay between the shooting stars:

CodePen Embed Fallback

 

Can’t hide your animation during the delay?

If you need to keep your animation on screen during the delay, there is another option besides hiding. You can still use a second set of @keyframes, but animate a CSS property in a way that counteracts or nullifies the motion of the primary animation. For example, if your main animation uses translateX, you can animate left or margin-left in your set of delay @keyframes.

Here’s a couple of examples:

Pause by changing transform-origin:

CodePen Embed Fallback

Pause by counter-acting transform: translateX by animating the left property:

CodePen Embed Fallback

In the case of the pausing the translateX animation, you’ll need to get fancier with the @keyframes if you need to pause the animation for more than just a single iteration:

/* pausing the animation for three iterations */ @keyframes slide-left-pause { 25%, 50%, 75% { left: 0; } 37.5%, 62.5%, 87.5% { left: -100px; } 100% { left: 0; } }

You may get some slight jitter during the pause. In the translateX example above, there’s some minor vibration on the ball during the slide-left-pause as the animations fight each other for dominance.

Wrap up

The best option performance-wise is to hide the element during the delay or animate transform. Animating properties like left, margin, width are much more intense on a processor than animating opacity (although the contain property appears to be changing that).

If you have any insights or comments on this idea, let me know!

Thanks to Yusuke Nakaya for the original shooting stars CSS animation that I forked on CodePen.

The post A New Way to Delay Keyframes Animations appeared first on CSS-Tricks.

Jetpack Scan

Css Tricks - Tue, 06/02/2020 - 4:10am

Fresh from the Jetpack team at Automattic, today, comes Jetpack Scan. Jetpack Scan scans all the files on your site looking for anything suspicious or malicious and lets you know, or literally fixes it for you with your one-click approval.

This kind of security scanning is very important to me. It’s one of those sleep better at night features, where I know I’m doing all I can do for the safety of my site.

It’s not fun to admit, but I bet in my decade-and-a-half of building WordPress sites, I’ve had half a dozen of them probably have some kind of malicious thing happen. It’s been a long time because I know more, take security way more seriously, and use proper tooling like this to make sure it can’t. But an example is that a malicious actor somehow edits files on your site. One edit to your wp-config.php file could easily take down your site. One edit to your single.php file could put malicious/spammy content on every single blog post. One sketchy plugin can literally do anything to your site. I want to know when any foul play is detected like this.

The new Jetpack.com Dashboard

I’m comforted by the idea that it is Automattic themselves who are checking my site every day and making sure it is clean. Aside from the fact that this is a paid service so they have all that incentive to make sure this does its job, they have the reputation of WordPress itself to uphold here, which is the kind of alignment I like to see in products.

If you’re a user or are familiar with VaultPress, which did backups and security scans, this is an evolution of that. This brings that world into a new dashboard on Jetpack.com (for scans and backup), meaning you can manage all this right from there. Note that this dashboard is for new customers of Jetpack Scan and Backup right now and will soon be available for all existing customers also.

That’s what Jetpack, more broadly, does: it brings powerful abilities of the WordPress.com cloud to your site. For example, backups, CDN hosted assets, instant search, related posts, automatic plugin updates, and more. All of that burden is lifted from your site and done on theirs.

Our page going into the many features of Jetpack we use on this site.

This is also another step toward more à la carte offerings from Jetpack. If you only want this feature and not anything else Jetpack offers, well, you’re in luck. Just like backups, that’s how this feature is sold. Want it? Pay just for it. Don’t want it? Don’t pay for it.

The intro offer (limited time) is $7/month or $70/year. So getting Jetpack Scan right away is your best value.

Their announcement post is out too. High five gang, very nice release.

The post Jetpack Scan appeared first on CSS-Tricks.

Overlapping Header with CSS Grid

Css Tricks - Mon, 06/01/2020 - 4:43am

Snook shows off a classic design with an oversized header up top, and a content area that is “pulled up” into that header area. My mind goes to the same place:

Historically, I’ve done this with negative margins. The header has a height that adds a bunch of padding to the bottom and then the body gets a margin-top: -50px or whatever the design calls for.

If you match the margin and padding with a situation like this, it’s not exactly magic numbers, but it still doesn’t feel great to me beaus they’re still numbers you need to keep in sync across totally different elements.

His idea? Build it with CSS grid instead. Definitely feels much more robust.

Random coinsidence, I was reading Chen Hui Jing’s “The one in black and orange” post and the pattern showed up there as well.

(I ended up doing a video on this).

Direct Link to ArticlePermalink

The post Overlapping Header with CSS Grid appeared first on CSS-Tricks.

Increment Issue 13: Frontend

Css Tricks - Sat, 05/30/2020 - 2:17am

Increment is a beautiful quarterly magazine (print and web) published by Stripe “about how teams build and operate software systems at scale”. While there is always stuff about making websites in general, this issue is the first focused on front-end¹ development.

I’ve got an article in there: When frontend means full stack. I’ll probably someday port it over here and perhaps add some more context (there were some constraints for print) but I love how it turned out on their site! A taste:

We handle this growing responsibility in different ways. Even though we all technically fall within the same big-tent title, many frontend developers wind up specializing. Often, we don’t have a choice. The term “unicorn” once described the extremely rare person who was good at both frontend and backend development, but these days it’s just as rare to find people skilled at the full spectrum of frontend development. In fact, the term “full stack” has largely come to mean “a frontend developer who does a good amount of the stuff a backend developer used to do.”

The whole issue is chock full of wonderful authors:

And the article that is the most right up my alley, Why is CSS . . . the way it is? by Chris Lilley. It’s somehow astonishing, gutwrenching, understandable, and comfortable to know that CSS evolves like any other software project. Sometimes thoughtfully and carefully, and sometimes with a meh, we’ll fix it later.

Once a feature is in place, it’s easier to slightly improve it than to add a new, better, but completely different feature that does the same thing.

This explains, for example, why list markers were initially specified in CSS by expanding the role of float. (The list marker was floated left so the list item text wrapped around it to the right.) That effort was abandoned and replaced by the list-style-position property, whose definition currently has the following, not very confidence-inspiring inline issue: “This is handwavey nonsense from CSS2, and needs a real definition.”

That’s a damn fine collection of writings on front end if you ask me.

A big thank you to Sid Orlando and Molly McArdle who helped me through the process and seem to do a great job running the ship over there.

  1. The issue uses “frontend” throughout, and I appreciate them having a styleguide and being consistent about it. But I can’t bring myself to use it. &#x1f517; The term “front-end” is correct when used as a compound adjective, and the term “front end” is correct when used as a noun.

The post Increment Issue 13: Frontend appeared first on CSS-Tricks.

Global CSS options with custom properties

Css Tricks - Fri, 05/29/2020 - 12:26pm

With a preprocessor, like Sass, building a logical “do this or don’t” setting is fairly straightforward:

$option: false; @mixin doThing { @if $option { do-thing: yep; } } .el { @include doThing; }

Can we do that in native CSS with custom properties? Mark Otto shows that we can. It’s just a smidge different.

html { --component-shadow: 0 .5rem 1rem rgba(0,0,0,.1); } .component { box-shadow: var(--component-shadow); } <!-- override the global anywhere more specific! like <div class="component remove-shadow"> or <body class="remove-shadow"> --> .remove-shadow { --component-shadow: none; }

Direct Link to ArticlePermalink

The post Global CSS options with custom properties appeared first on CSS-Tricks.

Jamstack News!

Css Tricks - Fri, 05/29/2020 - 4:56am

I totally forgot that the Jamstack Conf was this week but thankfully they’ve already published the talks on the Jamstack YouTube channel. I’m really looking forward to sitting down with these over a coffee while I also check out Netlify’s other big release today: Build Plugins.

These are plugins that run whenever your site is building. One example is the A11y plugin that will fail a build if accessibility failures are detected. Another minifies HTML and there’s even one that inlines critical CSS. What’s exciting is that these build plugins are kinda making complex Gulp/Grunt environments the stuff of legend. Instead of going through the hassle of config stuff, build plugins let Netlify figure it all out for you. And that’s pretty neat.

Also, our very own Sarah Drasner wrote just about how to create your first Netlify Build Plugin. So, if you have an idea for something that you could share with the community, then that may be the best place to start.

Direct Link to ArticlePermalink

The post Jamstack News! appeared first on CSS-Tricks.

Jamstack News!

Css Tricks - Fri, 05/29/2020 - 4:56am

I totally forgot that the Jamstack Conf was this week but thankfully they’ve already published the talks on the Jamstack YouTube channel. I’m really looking forward to sitting down with these over a coffee while I also check out Netlify’s other big release today: Build Plugins.

These are plugins that run whenever your site is building. One example is the A11y plugin that will fail a build if accessibility failures are detected. Another minifies HTML and there’s even one that inlines critical CSS. What’s exciting is that these build plugins are kinda making complex Gulp/Grunt environments the stuff of legend. Instead of going through the hassle of config stuff, build plugins let Netlify figure it all out for you. And that’s pretty neat.

Also, our very own Sarah Drasner wrote just about how to create your first Netlify Build Plugin. So, if you have an idea for something that you could share with the community, then that may be the best place to start.

Direct Link to ArticlePermalink

The post Jamstack News! appeared first on CSS-Tricks.

Core Web Vitals

Css Tricks - Thu, 05/28/2020 - 12:44pm

Core Web Vitals is what Google is calling a a new collection of three web performance metrics:

  1. LCP: Largest Contentful Paint
  2. FID: First Input Delay
  3. CLS: Cumulative Layout Shift

These are all measurable. They aren’t in Lighthouse (e.g. the Audits tab in Chrome DevTools) just yet, but sounds like that’s coming up soon. For now, an open source library will get you the numbers. There is also a browser extension (that feels pretty alpha as you have to install it manually).

That’s all good to me. I like seeing web performance metrics evolve into more meaningful numbers. I’ve spent a lot of time in my days just doing stuff like reducing requests and shrinking assets, which is useful, but kind of a side attack to web performance. These metrics are what really matter because they are what users actually see and experience.

The bigger news came today though in that they are straight up telling us: Core Web Vitals matter for your SEO:

Today, we’re building on this work and providing an early look at an upcoming Search ranking change that incorporates these page experience metrics. We will introduce a new signal that combines Core Web Vitals with our existing signals for page experience to provide a holistic picture of the quality of a user’s experience on a web page.

Straight up, these numbers matter for SEO (or they will soon).

And they didn’t bury the other lede either:

As part of this update, we’ll also incorporate the page experience metrics into our ranking criteria for the Top Stories feature in Search on mobile, and remove the AMP requirement from Top Stories eligibility.

AMP won’t be required for the SERP carousel thing, which was the #1 driver of AMP adoption. I can’t wait to see my first non-AMP page up there! I know some features will be unavailable, like the ability to swipe between stories (because that relies on things like the Google AMP cache), but whatever, bring it on. Let AMP just be a thing people use because they want to, and not because they have to.

The post Core Web Vitals appeared first on CSS-Tricks.

A First Look at `aspect-ratio`

Css Tricks - Thu, 05/28/2020 - 12:01pm

Oh hey! A brand new property that affects how a box is sized! That’s a big deal. There are lots of ways already to make an aspect-ratio sized box (and I’d say this custom properties based solution is the best), but none of them are particularly intuitive and certainly not as straightforward as declaring a single property.

So, with the impending arrival of aspect-ratio (MDN, and not to be confused with the media query version), I thought I’d take a look at how it works and try to wrap my mind around it.

Shout out to Una where I first saw this and boy howdy did it strike interest in folks. Here’s me playing around a little.

Just dropping aspect-ratio on an element alone will calculate a height based on the auto width.

Without setting a width, an element will still have a natural auto width. So the height can be calculated from the aspect ratio and the rendered width.

.el { aspect-ratio: 16 / 9; } Demo If the content breaks out of the aspect ratio, the element will still expand.

The aspect ratio becomes ignored in that situation, which is actually nice. That’s why the pseudo-element tactic for aspect ratios was popular, because it didn’t put us in dangerous data loss or awkward overlap territory when content got too much.

But if you want to constrain the height to the aspect ratio, you can by adding a min-height: 0;:

Demo If the element has either a height or width, the other is calculated from the aspect ratio.

So aspect-ratio is basically a way of setting the other direction when you only have one.

Demo If the element has both a height and width, aspect-ratio is ignored.

The combination of an explicit height and width is “stronger” than the aspect ratio.

Factoring in min-* and max-*

There is always a little tension between width, min-width, and max-width (or the height versions). One of them always “wins.” It’s generally pretty intuitive.

If you set width: 100px; and min-width: 200px; then min-width will win. So, min-width is either ignored because you’re already over it, or wins. Same deal with max-width: if you set width: 100px; and max-width: 50px; then max-width will win. So, max-width is either ignored because you’re already under it, or wins.

It looks like that general intuitiveness carries on here: the min-* and max-* properties will either win or are irrelevant. And if they win, they break the aspect-ratio.

.el { aspect-ratio: 1 / 4; height: 500px; /* Ignored, because width is calculated to be 125px */ /* min-width: 100px; */ /* Wins, making the aspect ratio 1 / 2 */ /* min-width: 250px; */ } With value functions

Aspect ratios are always most useful in fluid situations, or anytime you essentially don’t know one of the dimensions ahead of time. But even when you don’t know, you’re often putting constraints on things. Say 50% wide is cool, but you only want it to shrink as far as 200px. You might do width: max(50%, 200px);. Or constrain on both sides with clamp(200px, 50%, 400px);.

This seems to work intuitively:

.el { aspect-ratio: 4 / 3; width: clamp(200px, 50%, 400px); }

But say you run into that minimum 200px, and then apply a min-width of 300px? The min-width wins. It’s still intuitive, but it gets brain-bending because of how many properties, functions, and values can be involved.

Maybe it’s helpful to think of aspect-ratio as the weakest way to size an element?

It will never beat any other sizing information out, but it will always do its sizing if there is no other information available for that dimension.

The post A First Look at `aspect-ratio` appeared first on CSS-Tricks.

Why we at $FAMOUS_COMPANY Switched to $HYPED_TECHNOLOGY

Css Tricks - Thu, 05/28/2020 - 12:01pm

Too funny:

After careful consideration, we settled on rearchitecting our platform to use $FLASHY_LANGUAGE and $HYPED_TECHNOLOGY. Not only is $FLASHY_LANGUAGE popular according to the Stack Overflow developer survey, it’s also cross platform; we’re using it to reimplement our mobile apps as well. Rewriting our core infrastructure was fairly straightforward: as we have more engineers than we could possibly ever need or even know what to do with, we simply put a freeze on handling bug reports and shifted our effort to $HYPED_TECHNOLOGY instead. We originally had some trouble with adapting to some of $FLASHY_LANGUAGE’s quirks, and ran into a couple of bugs with $HYPED_TECHNOLOGY, but overall their powerful new features let us remove some of the complexity that our previous solution had to handle.

There is absolutely no way Saagar Jha is poking at this or this.

Direct Link to ArticlePermalink

The post Why we at $FAMOUS_COMPANY Switched to $HYPED_TECHNOLOGY appeared first on CSS-Tricks.

PureCSS Gaze

Css Tricks - Thu, 05/28/2020 - 4:37am

Diana Smith with another mind-bending all HTML & CSS painting.

I love that these occupy a special place on the “Should I draw this in CSS?” curve. Things like simple shapes are definitely on the “yes” side of the curve. Then there’s a large valley where things get a little too impractical to draw that way, and using some other image format (e.g. SVG) makes way more sense.

Diana’s work pulls the curve back up to the “yes” side. Not only because it’s proof that CSS can be an amazing expressionistic art tool, but also from a performance standpoint — it’s only 2 KB of HTML and 10 KB of CSS.

Direct Link to ArticlePermalink

The post PureCSS Gaze appeared first on CSS-Tricks.

Get Programmatic Control of your Builds with Netlify Build Plugins

Css Tricks - Wed, 05/27/2020 - 4:14am

Today at Jamstack_Conf, Netlify announced Build Plugins. What it does is allow you to have particular hooks for events within your build, like when the build starts or ends. What’s nice about them is that they’re just a plain ‘ol JavaScript object, so you can insert some logic or kick off a library just the way you typically would within your application.

A “Build” is when you give your site to Netlify either via GitHub/GitLab/etc., or by literally just dropping the directory into the interface, Netlify will process all the assets, download and install packages, and generate a static version of the site to deploy to CDNs all around the world.

What the Build Plugin does is give you access to key points in time during that process, for instance, onPreBuild, onPostBuild, onSuccess, and so forth. You can execute some logic at those specific points in time, like this:

module.exports = { onPreBuild: () => { console.log('Hello world from onPreBuild event!') }, }

You don’t only have to build them yourself, either! You can use build plugins that have been made by the community. There are very interesting ones, such as a11y, Cypress for testing, Inline Critical CSS, and my personal favorite, Subfont, which optimizes fonts for you in a really incredible way (you can watch a video about that).

Enable them through the dashboard through a few button clicks:

If you’d like to learn more, check out the announcement post here! Happy building!

The post Get Programmatic Control of your Builds with Netlify Build Plugins appeared first on CSS-Tricks.

Responsive web design turns ten.

Css Tricks - Wed, 05/27/2020 - 3:41am

Ethan on the thinking and research that inspired the term:

Around that time, my partner Elizabeth visited the High Line in New York City shortly after it opened. When she got back, she told me about these wheeled lounge chairs she saw in one section, and how people would move them apart for a bit of solitude, or push a few chairs together to sit closer to friends. We got to excitedly chatting about them. I thought there was something really compelling about that image: a space that could be controlled, reshaped, and redesigned by the people who moved through it.

I remember spending that evening reading more about those chairs and, from there, about more dynamic forms of architecture. I read about concepts for walls built with tensile materials and embedded sensors, and how those walls could bend and flex as people drew near to them. I read about glass walls that could become opaque at the flip of a switch, or when movement was detected. I even bought a rather wonderful book on the subject, Interactive Architecture, which described these new spaces as “a conversation” between physical objects or spaces, and the people who interacted with them.

After a few days of research, I found some articles that alternated between two different terms for the same concept. They’d call it interactive architecture, sure, but then they’d refer to it with a different name: responsive architecture.

Fascinating.

Responsive web design is so locked in now a decade later it’s just an assumption. I would have called it an assumption in half that time. My answer in an interview…

Is responsive something that you have to sell in any more or does everyone get it now?

I think that responsive design was an assumption in 2015. Even then, if you delivered a website to a client that was just a zoomed out “desktop” website they would assume it’s broken and that you didn’t really do your job. Today, even more so. It’s just not done.

The technical side of responsive design is fascinating to me of course. Even Google has guides on the subject and highly encourages this approach. But the core technical implementation isn’t particularly complex. Stay fluid; use some @media queries to restyle things as needed.

The bigger deal in the last decade was the impact on businesses. Adjusting workflows to accommodate this style of thinking. Combining teams of developers who used to work on entirely different codebases now working on a single codebase. The impact at organizations wasn’t nearly as straightforward as the technology of it all.

There is a resonance between that and more recent shifts in the world of building websites, like the astounding rise of design systems and, even more so, the Coup d’état of JavaScript.

Direct Link to ArticlePermalink

The post Responsive web design turns ten. appeared first on CSS-Tricks.

A Guide to the Responsive Images Syntax in HTML

Css Tricks - Tue, 05/26/2020 - 12:15pm
Only View Code Snippets

This guide is about the HTML syntax for responsive images (and a little bit of CSS for good measure). The responsive images syntax is about serving one image from multiple options based on rules and circumstances. There are two forms of responsive images, and they’re for two different things:

If your only goal is…

Increased Performance

Then what you need is…

<img srcset="" src="" alt="" >

There is a lot of performance gain to be had by using responsive images. Image weight has a huge impact on pages’ overall performance, and responsive images are one of the best things that you can do to cut image weight. Imagine the browser being able to choose between a 300×300 image or a 600×600. If the browser only needs the 300×300, that’s potentially a 4× bytes-over-the-wire savings! Savings generally go up as the display resolution and viewport size go down; on the smallest screens, a couple of case studies have shown byte savings of 70–90%.

Using srcset

If you also need…

Design Control

Then what you need is…

<picture> <source srcset="" media=""> <source srcset="" media=""> <img src="" alt=""> </picture>

Another perfectly legit goal with responsive images is not just to serve different sizes of the same image, but to serve different images. For example, cropping an image differently depending on the size of the screen and differences in the layout. This is referred to as “art direction.”

The <picture> element is also used for fallback image types and any other sort of media query switching (e.g. different images for dark mode). You get greater control of what browsers display.

Using <picture>

There is a lot to talk about here, so let’s go through both syntaxes, all of the related attributes and values, and talk about a few related subjects along the way, like tooling and browsers.

Table of Contents Using srcset

The <img srcset="" src="" alt=""> syntax is for serving differently-sized versions of the same image. You could try to serve entirely different images using this syntax, but browsers assume that everything in a srcset is visually-identical and will choose whichever size they think is best, in impossible-for-you-to-predict ways. So I wouldn’t reccomend it.

Perhaps the easiest-possible responsive images syntax is adding a srcset attribute with x descriptors on the images to label them for use on displays with different pixel-densities.

<img alt="A baby smiling with a yellow headband." src="baby-lowres.jpg" srcset="baby-highres.jpg 2x" >

Here, we’ve made the default (the src) the “low res” (1×) copy of the image. Defaulting to the smallest/fastest resources is usually the smart choice. We also provide a 2× version. If the browser knows it is on a higher pixel-density display (the 2x part), it will use that image instead.

Demo <img alt="A baby smiling with a yellow headband." src="baby-lowres.jpg" srcset=" baby-high-1.jpg 1.5x, baby-high-2.jpg 2x, baby-high-3.jpg 3x, baby-high-4.jpg 4x, baby-high-5.jpg 100x " >

You can do as many pixel-density variants as you like.

While this is cool and useful, x descriptors only account for a small percentage of responsive images usage. Why? They only let browsers adapt based on one thing: display pixel-density. A lot of times, though, our responsive images are on responsive layouts, and the image’s layout size is shrinking and stretching right along with the viewport. In those situations, the browser needs to make decisions based on two things: the pixel-density of the screen, and the layout size of the image. That’s where w descriptors and the sizes attribute come in, which we’ll look at in the next section.

Using srcset / w + sizes

This is the good stuff. This accounts for around 85% of responsive images usage on the web. We’re still serving the same image at multiple sizes, only we’re giving the browser more information so that it can adapt based on both pixel-density and layout size.

<img alt="A baby smiling with a yellow headband." srcset=" baby-s.jpg 300w, baby-m.jpg 600w, baby-l.jpg 1200w, baby-xl.jpg 2000w " sizes="70vmin" >

We’re still providing multiple copies of the same image and letting the browser pick the most appropriate one. But instead of labeling them with a pixel density (x) we’re labelling them with their resource width, using w descriptors. So if baby-s.jpg is 300×450, we label it as 300w.

Using srcset with width (w) descriptors like this means that it will need to be paired with the sizes attribute so that the browser will know how large of a space the image will be displaying in. Without this information, browsers can’t make smart choices.

Demo Creating accurate sizes

Creating sizes attributes can get tricky. The sizes attribute describes the width that the image will display within the layout of your specific site, meaning it is closely tied to your CSS. The width that images render at is layout-dependent rather than just viewport dependent!

Let’s take a look at a fairly simple layout with three breakpoints. Here’s a video demonstrating this:

Demo

The breakpoints are expressed with media queries in CSS:

body { margin: 2rem; font: 500 125% system-ui, sans-serif; } .page-wrap { display: grid; gap: 1rem; grid-template-columns: 1fr 200px; grid-template-areas: "header header" "main aside" "footer footer"; } @media (max-width: 700px) { .page-wrap { grid-template-columns: 100%; grid-template-areas: "header" "main" "aside" "footer"; } } @media (max-width: 500px) { body { margin: 0; } }

The image is sized differently at each breakpoint. Here’s a breakdown of all of the bits and pieces that affect the image’s layout width at the largest breakpoint (when the viewport is wider than 700px):

The image is as wide as 100vw minus all that explicitly sized margin, padding, column widths, and gap.
  • At the largest size: there is 9rem of explicit spacing, so the image is calc(100vw - 9rem - 200px) wide. If that column used a fr unit instead of 200px, we’d kinda be screwed here.
  • At the medium size: the sidebar is dropped below, so there is less spacing to consider. Still, we can do calc(100vw - 6rem) to account for the margins and padding.
  • At the smallest size: the body margin is removed, so just calc(100vw - 2rem) will do the trick.

Phew! To be honest, I found that a little challenging to think out, and made a bunch of mistakes as I was creating this. In the end, I had this:

<img ... sizes=" (max-width: 500px) calc(100vw - 2rem), (max-width: 700px) calc(100vw - 6rem), calc(100vw - 9rem - 200px) " />

A sizes attribute that gives the browser the width of the image across all three breakpoints, factoring in the layout grid, and all of the surrounding gap, margin, and padding that end up impacting the image’s width.

Now wait! Drumroll! &#x1f941;&#x1f941;&#x1f941;That’s still wrong. I don’t understand why exactly, because to me that looks like it 100% describes what is happening in the CSS layout. But it’s wrong because Martin Auswöger’s RespImageLint says so. Running that tool over the isolated demo reports no problems except the fact that the sizes attribute is wrong for some viewport sizes, and should be:

<img ... sizes=" (min-width: 2420px) 2000px, (min-width: 720px) calc(94.76vw - 274px), (min-width: 520px) calc(100vw - 96px), calc(100vw - 32px) " >

I don’t know how that’s calculated and it’s entirely unmaintainable by hand, but, it’s accurate. Martin’s tool programmatically resizes the page a bunch and writes out a sizes attribute that describes the actual, observed width of the image over a wide range of viewport sizes. It’s computers, doing math, so it’s right. So, if you want a super-accurate sizes attribute, I’d recommend just putting a wrong one on at first, running this tool, and copying out the correct one.

For an even deeper dive into all this, check out Eric Portis’ w descriptors and sizes: Under the hood.

Being more chill about sizes

Another option is use the Horseshoes & Hand Grenades Method™ of sizes (or, in other words, close counts). This comes highly suggested.

For example, sizes="96vw" says, “This image is going to be pretty big on the page — almost the full width — but there will always be a little padding around the edges, so not quite. Or sizes="(min-width: 1000px) 33vw, 96vw" says, “This image is in a three-column layout on large screens and close to full-width otherwise.” Practicality-wise, this can be a sane solution.

You might find that some automated responsive image solutions, which have no way of knowing your layout, make a guess — something like sizes="(max-width: 1000px) 100vw, 1000px". This is just saying, “Hey we don’t really know much about this layout, but we’re gonna take a stab and say, worst case, the image is full-width, and let’s hope it never renders larger than 1000px”.

Abstracting sizes

I’m sure you can imagine how easy it is to not only get sizes wrong, but also have it become wrong over time as layouts change on your site. It may be smart for you to abstract it using a templating language or content filter so that you can change the value across all of your images more easily.

I’m essentially talking about setting a sizes value in a variable once, and using that variable in a bunch of different <img> elements across your site. Native HTML doesn’t offer that, but any back end language does; for instance, PHP constants, Rails config variables, the React context API used for a global state variable, or variables within a templating language like Liquid can all be used to abstract sizes.

<?php // Somewhere global $my_sizes = ""; ?> <img srcset="" src="" alt="" sizes="<?php echo $my_sizes; ?>" /> “Browser’s choice”

Now that we have a sizes attribute in place, the browser knows what size (or close to it) the image will render at and can work its magic. That is, it can do some math that factors in the pixel density of the screen, and the size that the image will render at, then pick the most appropriately-sized image.

The math is fairly straightforward at first. Say you’re about to show an image that is 40vw wide on a viewport that is 1200px wide, on a 2x pixel-density screen. The perfect image would be 960 pixels wide, so the browser is going to look for the closest thing it’s got. The browser will always calculate a target size that it would prefer based on the viewport and pixel-density situations, and what it knows from sizes, and compare that target to what it’s got to pick from in srcset. How browsers do the picking, though, can get a little weird.

A browser might factor more things into this equation if it chooses to. For example, it could consider the user’s current network speeds, or whether or not the user has flipped on some sort of “data saver” preference. I’m not sure if any browsers actually do this sort of thing, but they are free to if they wish as that’s how the spec was written. What some browsers sometimes choose to do is pull from cache. If the math shows they should be using a 300px image, but they already have a 600px in local cache, they will just use that. Smart. Room for this sort of thing is a strength of the srcset/sizes syntax. It’s also why you always use different sizes of the same image, within srcset: you’ve got no way to know which image is going to be selected. It’s the browser’s choice.

This is weird. Doesn’t the browser already know this stuff?

You might be thinking, “Uhm why do I have to tell the browser how big the image will render, doesn’t it know that?” Well, it does, but only after it’s downloaded your HTML and CSS and laid everything out. The sizes attribute is about speed. It gives the browser enough information to make a smart choice as soon as it sees your <img>.

<img data-sizes="auto" data-srcset=" responsive-image1.jpg 300w, responsive-image2.jpg 600w, responsive-image3.jpg 900w" class="lazyload" />

Now you might be thinking, “But what about lazy-loaded images?” (as in, by the time a lazy-loaded image is requested, layout’s already been done and the browser already knows the image’s render size). Well, good thinking! Alexander Farkas’ lazysizes library writes out sizes attributes automatically on lazyload, and there’s an ongoing discussion about how to do auto-sizes for lazy-loaded images, natively.

sizes can be bigger than the viewport

Quick note on sizes. Say you have an effect on your site so that an image “zooms in” when it’s clicked. Maybe it expands to fill the whole viewport, or maybe it zooms even more, so that you can see more detail. In the past, we might have had to swap out the src on click in order to switch to a higher-res version. But now, assuming a higher-res source is already in the srcset, you can just change the sizes attribute to something huge, like 200vw or 300vw, and the browser should download the super-high-res source automatically for you. Here’s an article by Scott Jehl on this technique.

↩️ Back to top

Using <picture>

Hopefully, we’ve beaten it into the ground that <img srcset="" sizes="" alt=""> is for serving differently-sized versions of the same image. The <picture> syntax can do that too, but the difference here is that the browser must respect the rules that you set. That’s useful when you want to change more than just the resolution of the loaded image to fit the user’s situation. This intentional changing of the image is usually called “art direction.”

Art Direction <picture> <source srcset="baby-zoomed-out.jpg" media="(min-width: 1000px)" /> <source srcset="baby.jpg" media="(min-width: 600px)" /> <img src="baby-zoomed-in.jpg" alt="Baby Sleeping" /> </picture>

This code block is an example of what it might look like to have three stages of an “art directed” image.

  • On large screens, show a zoomed-out photo.
  • On medium screens, show that same photo, zoomed in a bit.
  • On small screens, zoom in even more.

The browser must respect our media queries and will swap images at our exact breakpoints. That way, we can be absolutely sure that nobody on a small screen will see a tiny, zoomed-out image, which might not have the same impact as one of the zoomed-in versions.

Here’s a demo, written in Pug to abstract out some of the repetitive nature of <picture>.

CodePen Embed Fallback Art direction can do a lot more than just cropping

Although cropping and zooming like this is the most common form of art direction by far, you can do a lot more with it. For instance, you can:

Sky’s the limit, really.

Combining source and srcset

Because <source> also uses the srcset syntax, they can be combined. This means that you can still reap the performance benefits of srcset even while swapping out visually-different images with <source>. It gets pretty verbose though!

<picture> <source srcset=" baby-zoomed-out-2x.jpg 2x, baby-zoomed-out.jpg " media="(min-width: 1000px)" /> <source srcset=" baby-2x.jpg 2x, baby.jpg " media="(min-width: 600px)" /> <img srcset=" baby-zoomed-out-2x.jpg 2x " src="baby-zoomed-out.jpg" alt="Baby Sleeping" /> </picture>

The more variations you create and the more resized versions you create per variation, the more verbose this code has to get.

Fallbacks for modern image formats

The <picture> element is uniquely suited to being able to handle “fallbacks.” That is, images in cutting-edge formats that not all browsers might be able to handle, with alternative formats for browsers that can’t load the preferred, fancy one. For example, let’s say you want to use an image in the WebP format. It’s a pretty great image format, often being the most performant choice, and it’s supported everywhere that the <picture> element is, except Safari. You can handle that situation yourself, like:

<picture> <source srcset="party.webp"> <img src="party.jpg" alt="A huge party with cakes."> </picture>

This succeeds in serving a WebP image to browsers that support it, and falls back to a JPEG image, which is definitely supported by all browsers.

Here’s an example of a photograph (of me) at the exact same size where the WebP version is about 10% (!!!) of the size of the JPEG.

CodePen Embed Fallback

How do you create a WebP image? Well, it’s more of a pain in the butt than you’d like it to be, that’s for sure. There are online converters, command line tools, and some modern design software, like Sketch, helps you export in that format. My preference is to use an image hosting CDN service that automatically sends images in the perfect format for the requesting browser, which makes all this unnecessary (because you can just use img/srcset).

WebP isn’t the only player like this. Safari doesn’t support WebP, but does support a format called JPG 2000 which has some advantages over JPEG. Internet Explorer 11 happens to support an image format called JPEG-XR which has different advantages. So to hit all three, that could look like:

<picture> <source srcset="/images/cereal-box.webp" type="image/webp" /> <source srcset="/images/cereal-box.jp2" type="image/jp2" /> <img src="/images/cereal-box.jxr" type="image/vnd.ms-photo" /> </picture>

This syntax (borrowed form a blog post by Josh Comeau) supports all three of the “next-gen” image formats in one go. IE 11 doesn’t support the <picture> syntax, but it doesn’t matter because it will get the <img> fallback which is in the JPEG-XR format it understands.

Estelle Weyl also covered this idea in a 2016 blog post on image optimization.

↩️ Back to top

Where do you get the differently-sized images?

You can make them yourself. Heck, even the free Preview app on my Mac can resize an image and “Save As.”

The Mac Preview app resizing an image, which is something that literally any image editing application (including Photoshop, Affinity Designer, Acorn, etc.) can also do. Plus, they often help by exporting the variations all at once.

But that’s work. It’s more likely that the creation of variations of these images is automated somehow (see the section below) or you use a service that allows you to create variations just by manipulating the URL to the image. That’s a super common feature of any image hosting/image CDN service. To name a few:

Not only do these services offer on-the-fly image resizing, they also often offer additional stuff, like cropping, filtering, adding text, and all kinds of useful features, not to mention serving assets efficiently from a CDN and automatically in next-gen formats. That makes them a really strong choice for just about any website, I’d say.

Here’s Glen Maddern in a really great screencast talking about how useful Image CDNs can be:

Design software is booming more aware that we often need multiple copies of images. The exporting interface from Figma is pretty nice, where any given selection can be exported. It allows multiple exports at once (in different sizes and formats) and remembers what you dod the last time you exported.

Exporting in Figma Automated responsive images

The syntax of responsive images is complex to the point that doing it by hand is often out of the question. I’d highly recommend automating and abstracting as much of this away as possible. Fortunately, a lot of tooling that helps you build websites knows this and includes some sort of support for it. I think that’s great because that’s what software should be doing for us, particularly when it is something that is entirely programmatic and can be done better by code than by humans. Here are some examples…

  • Cloudinary has this responsive breakpoints tool including an API for generating the perfect breakpoints.
  • WordPress generates multiple versions of images and outputs in the responsive images syntax by default.
  • Gatsby has a grab-bag of plugins for transforming and implementing images on your site. You ultimately implement them with gatsby-image, which is a whole fancy thing for implementing responsive images and other image loading optimizations. Speaking of React, it has component abstractions like “An Almost Ideal React Image Component” that also does cool stuff.
  • Nicolas Hoizey’s Images Responsiver Node module (and it’s Eleventy plugin) makes a ton of smart markup choices for you, and pairs nicely with a CDN that can handle the on-the-fly resizing bits.
  • These are just a few examples! Literally anything you can do to make this process easier or automatic is worth doing.
Here’s me inspecting an image in a WordPress blog post and seeing a beefy srcset with a healthy amount of pre-generated size options and a sizes attribute tailored to this theme. A landing page for gatsby-image explaining all of the additional image loading stuff it can do.

I’m sure there are many more CMSs and other software products that help automate away the complexities of creating the responsive images syntax. While I love that all this syntax exists, I find it all entirely too cumbersome to author by hand. Still, I think it’s worth knowing all this syntax so that we can build our own abstractions, or check in on the abstractions we’re using to make sure they are doing things correctly.

Related concepts
  • The object-fit property in CSS controls how an image will behave in its own box. For example, an image will normally “squish” if you change the dimensions to something different than its natural aspect ratio, but object-fit can be used to crop it or contain it instead.
  • The object-position property in CSS allows you to nudge an image around within its box.
What about responsive images in CSS with background images?

We’ve covered exactly this before. The trick is to use @media queries to change the background-image source. For example:

.img { background-image: url(small.jpg); } @media (min-width: 468px), (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { .img { background-image: url(large.jpg); } }

With this CSS syntax, depending on the browser conditions, the browser will only download one of the two images, which achieves the same performance goal that the responsive images syntax in HTML does. If it helps, think of the above as the CSS equivalent of the <picture> syntax: the browser must follow your rules and display what matches.

If you’re looking to let the browser choose the best option, like srcset/sizes, but in CSS, the solution is ultimately going to be the image-set() function. There’s two problems with image-set(), today, though:

  • Support for it isn’t there yet. Safari’s implementation leads the pack, but image-set() has been prefixed in Chrome for eight years, and it’s not there at all in Firefox.
  • Even the spec itself seems behind the times. For example, it only supports x descriptors (no w, yet).

Best to just use media queries for now.

Do you need to polyfill?

I’m pretty meh on pollyfilling any of this right this moment. There is a great polyfill though, called Picturefill, which will buy you full IE 9-11 support if you need that. Remember, though, that none of this stuff breaks to the point of not displaying any image at all in non-supporting browsers, assuming you have an <img src="" alt=""> in there somewhere. If you make the (fairly safe) assumption that IE 11 is running on a low-pixel-density desktop display, you can make your image sources reflect that by default and build out from there.

Other important image considerations
  • Optimizing quality: The point of responsive images is loading the smallest, most impactful resource that you can. You can’t achieve that without effectively compressing your image. You’re aiming for a “sweet spot” for every image, between looking good and being light. I like to let image hosting services solve this problem for me, but Etsy has a really great writeup of what they’ve been able to accomplish with infrastructure that they built themselves.
  • Serving from CDNs: Speaking of image hosting services, speed comes in many forms. Fast servers that are geographically close to the user are an important speed factor as well.
  • Caching: What’s better than loading less data over the network? Loading no data at all! That’s what HTTP caching is for. Using the Cache-Control header, you can tell the browser to hang on to images so that if the same image is needed again, the browser doesn’t have to go over the network to get it, which is a massive performance boost for repeat viewings.
  • Lazy loading: This is another way to avoid loading images entirely. Lazy loading means waiting to download an image until it is in or near the viewport. So, for example, an image way far down the page won’t load if the user never scrolls there.
Other good resources

(That I haven’t linked up in the post already!)

Browser Support

This is for srcset/sizes, but it’s the same for <picture>.

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

DesktopChromeFirefoxIEEdgeSafari3838No169Mobile / TabletAndroid ChromeAndroid FirefoxAndroidiOS Safari8168819.0-9.2

The post A Guide to the Responsive Images Syntax in HTML appeared first on CSS-Tricks.

CSS Tips for New Devs

Css Tricks - Tue, 05/26/2020 - 12:15pm

Amber Wilson has some CSS Tips for New Devs, like:

It’s not a good idea to fix shortcomings in your HTML with CSS. Fix your HTML first!

And…

You can change CSS right in your browser’s DevTools (to open them, right-click the browser window and choose “inspect” or “inspect element”). The great thing is, none of the styles will be saved so you can experiment here! Another great thing about the DevTools is the “computed styles” tab, because this shows you exactly what styles are currently applied to an element. This can be really helpful when it comes to debugging your CSS!

There are 24 tips there. I “counted” by using DevTools to change the <ul> to an <ol>. &#x1f609;

Direct Link to ArticlePermalink

The post CSS Tips for New Devs appeared first on CSS-Tricks.

Framer Web

Css Tricks - Tue, 05/26/2020 - 4:35am

The prototyping app Framer just launched the web version of their design tool and it looks pretty darn neat. I particularly love the design of the marketing site that explains how to use Framer and what sets it apart from other design tools. They have a ton of examples that you can pop open to explore as well, like this demo for how to make hover tooltips in the app:

I have to say that I love how the UI feels in Framer — both on the website and the design app itself. It all reminds me of the Oculus Quest UI with rounded corners and dark-mode inspired elements. I know it’s probably just a silly trend, but I like it!

Anyway, I’ve yet to dig into this fancy new tool too much but the animation effects appear to be quite magic and absolutely worth experimenting with.

Direct Link to ArticlePermalink

The post Framer Web appeared first on CSS-Tricks.

How to Convert a Date String into a Human-Readable Format

Css Tricks - Mon, 05/25/2020 - 4:13am

I’ll be the first to admit that I’m writing this article, in part, because it’s something I look up often and want to be able to find it next time. Formatting a date string that you get from an API in JavaScript can take many shapes — anything from loading all of Moment.js to have very finite control, or just using a couple of lines to update it. This article is not meant to be comprehensive, but aims to show the most common path of human legibility.

ISO 8601 is an extremely common date format. The “Z” at the end means the time in ISO 8601 format is using the UTC standard, i.e. no timezone. Here’s an example: 2020-05-25T04:00:00Z. When I bring data in from an API, it’s typically in ISO 8601 format.

If I wanted to format the above string in a more readable format, say May 25, 2020, I would do this:

const dateString = '2020-05-14T04:00:00Z' const formatDate = (dateString) => { const options = { year: "numeric", month: "long", day: "numeric" } return new Date(dateString).toLocaleDateString(undefined, options) }

Here’s what I’m doing…

First, I’m passing in options for how I want the output to be formatted. There are many, many other options we could pass in there to format the date in different ways. I’m just showing a fairly common example.

const options = { year: "numeric", month: "long", day: "numeric" }

Next, I’m creating a new Date instance that represents a single moment in time in a platform-independent format.

return new Date(dateString)

Finally, I’m using the .toLocaleDateString() method to apply the formatting options.

return new Date(dateString).toLocaleDateString(undefined, options)

Note that I passed in undefined. Not defining the value in this case means the time will be represented by whatever the default locale is. You can also set it to be a certain area/language. Or, for apps and sites that are internationalized, you can pass in what the user has selected (e.g. 'en-US' for the United States, 'de-DE' for Germany, and so forth). There’s a nice npm package that includes list of more locales and their codes.

Hope that helps you get started! And high fives to future Sarah for not having to look this up again in multiple places. &#x1f91a;

The post How to Convert a Date String into a Human-Readable Format appeared first on CSS-Tricks.

Syndicate content
©2003 - Present Akamai Design & Development.