Tag: Things

Three Things You Didn’t Know About AVIF

AVIF, the file format based on the AV1 video codec, is the latest addition to the next-gen image formats. Early reports and comparisons show good results compared to JPEG and WebP. However, even if browser support is good, AVIF is still on the bleeding edge in regards to encoding and decoding. Encoding, decoding, settings and parameters has been well discussed elsewhere. 

No doubt, AVIF images generate a smaller payload and are nice looking. In this post, we’ll take a closer look at issues to be aware or before you go all in on AVIF.

1. WebP is Better for Thumbnails

One interesting observation is that for small dimension images, WebP will produce lighter payload images than AVIF.

It’s probably possible to explain why, and tune the encoder to address this case. However, that is not an option for most people. Most people would probably rely on an image optimizer like squoosh.app or an image CDN like ImageEngine. The below comparison uses exactly these two alternatives for AVIF conversion. 

We see that WebP will generally produce images with a higher file size than AVIF. On larger dimension images, ImageEngine performs significantly better than squoosh.app.

Now, to the interesting observation. On images around 100px × 100px squoosh.app passes ImageEngine on effectiveness, but then also WebP catches up and for a 80px x 80px image. WebP is actually the most effective image measured in file size. 

The test performs relatively consistently on different types of images. For this illustration, this image from Picsum is used.

Pixels Original JPEG (bytes) Optimized WebP (bytes) ImageEngine AVIF (bytes) squoosh.app AVIF (bytes)
50 1,475 598 888 687
80 2,090 1,076 1,234 1,070
110 3,022 1,716 1,592 1,580
150 4,457 2,808 2,153 2,275
170 5,300 3,224 2,450 2,670
230 7,792 4,886 3,189 3,900
290 10,895 6,774 4,056 5,130

2. AVIF Might Not Be the Best for Product Images with High Entropy

Typically, a product page consists of images of the product, and when a user’s mouse hovers over or clicks on the product image, it zooms in to offer a closer look at the details.

It is worth noting that AVIF will in certain cases reduce the level of detail, or perceived sharpness, of the image when zoomed in. Especially on a typical product image where the background is blurred or has low entropy while foreground, and product, has more detail and possibly higher entropy.

Below is a zoomed in portion of a bigger product image (JPEG, AVIF) which clearly illustrates the difference between a regularly optimized JPEG versus an AVIF image optimized by squoosh.app.

The AVIF is indeed much lighter than the JPEG, but in this case the trade off between visual quality and lower file size has gone too far. This effect will not be as perceptible for all types of images, and therefore will be difficult to proactively troubleshoot in an automated build process that relies on responsive images syntax for format selection.

Moreover, unlike JPEG, AVIF does not support progressive rendering. For a typical product detail page, progressive rendering might provide a killer feature to improve key metrics like Largest Contentful Paint and other Core Web Vitals metrics. Even if a JPEG takes a little bit longer time to download due to its larger file size compared to AVIF, chances are that it will start rendering sooner than an AVIF thanks to its progressive rendering mechanism. This case is well illustrated by this video from Jake Achibald.

3. JPEG 2000 is Giving AVIF Tough Competition

The key selling point of AVIF is its extremely low file size relative to an acceptable visual image quality. Early blogs and reports have been focusing on this. However, JPEG2000 (or JP2) may in some cases be a better tool for the job. JPEG2000 is a relatively old file format and does not get the same level of attention as AVIF, even if the Apple side of the universe already supports JPEG2000.

To illustrate, let’s look at this adorable puppy. The AVIF file size optimized by squoosh.app is 27.9 KB with default settings. Converting the image to JPEG2000, again using ImageEngine, the file size is 26.7 KB. Not much difference, but enough to illustrate the case.

What about the visual quality? DSSIM is a popular way to compare how visually similar an image is to the original image. The DSSIM metric compares the original image to a converted file, with a lower value indicating better quality. Losslessly converting the AVIF and JPEG2000 version to PNG, the DSSIM score is like this:

DSSIM (0 = equal to original) Bytes
JPEG2000 0.019 26.7 KB
AVIF 0.012 27.9 KB

AVIF has slightly better DSSIM but hardly visible to the human eye.

Right Tool for the Job

The key takeaway from this article is that AVIF is hardly the “silver bullet,” or the one image format to rule them all. First of all, it is still very early in the development of both encoders and decoders. In addition, AVIF is yet another format to manage. Like Jake Archibald also concludes in his article, offering 3+ versions of each image on your webpage is a bit of a pain unless the entire workflow (resize, compress, convert, select, deliver) is all automated.

Also, like we’ve seen, just because a browser supports AVIF, it doesn’t mean that it is the best choice for your users.

Using responsive images and adding AVIF to the list of image formats to pre-create is better than not considering AVIF at all. A potential challenge is that the browser will then pick AVIF if it’s supported regardless of whether AVIF is the right tool or not.

However, using an image CDN like ImageEngine, will to a greater extent be able to dynamically choose between supported formats and make a qualified guess whether WEBP, JPEG2000 or AVIF will give the best user experience. Using an image CDN to automate the image optimization process will take into account browser compatibility, image payload size and visual quality.


The post Three Things You Didn’t Know About AVIF appeared first on CSS-Tricks.

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

CSS-Tricks

, , , , ,

Little Things on My Personal Site

I updated my personal website the other day. Always a fun project since it’s one of the few where it’s 100% just me. It’s my own personal playground with no other goal than making the site represent me to have a little fun. It’s not a complete re-write, just some new paint.

I thought I’d document little bits of it here just to hone in on some of the bits of trickery in the spirit of learning through sharing.

Screenshot of the entire length of the homepage of ChrisCoyier.net. Four major boxes of content: build-your-own bio in yellow, blog posts in purple, action items in red, and a video in blue.

Hoefler Fonts

I think the Inkwell family is super cool. I like mix and matching not just the weights but the serif and sans-serif and caps vs not.

From the Inkwell introduction post.

I used Inkwell in the last design as well, but I was worried that it was a little too jokey for blog post body copy. My writing is extremely casual, but not always, and Inkwell is way too jovial for serious topics. I went with Ideal Sans for body copy last time, but the pairing with Inkwell felt a little off.

This time I went with Whitney for general body copy, which is still pretty lighthearted, but works when the copy is more straight toned.

Blogroll

If you’re going to zebra-stripe a table, you’d do something like…

tr:nth-child(even) {   background-color: var(--color-1); } tr:nth-child(odd) {   background-color: var(--color-2); }

What if you wanted to rotate four colors though? It’s still :nth-child trickery, selecting every four, and then offsetting. Here, I’ll do it with list items in Sass (the nesting is nice, not having to repeat the selector):

li {   &:nth-child(4n) a {     color: $ blue;   }   &:nth-child(4n + 1) a {     color: $ yellow;   }   &:nth-child(4n + 2) a {     color: $ red;   }   &:nth-child(4n + 3) a {     color: $ purple;   } }

That’s what I did to build the colorized blogroll:

Note the Sass used above… I used Sass because it was already in use on the project. All I had to do was open CodeKit and the processing was ready-to-go.

Oh, and blogrolls are cool again.

Chill YouTube

I used this click-to-load-YouTube-(at all) technique which is still extremely clever. Having an <iframe> that behaves just like a YouTube embed would but only loading a simple static image (rather than heaps and heaps of resources) is great for performance and behaves essentially the same as a normal YouTube embed does.

<iframe   width="560"   height="315"   src="https://www.youtube.com/embed/Y8Wp3dafaMQ"   srcdoc="<style>*{padding:0;margin:0;overflow:hidden}html,body{height:100%}img,span{position:absolute;width:100%;top:0;bottom:0;margin:auto}span{height:1.5em;text-align:center;font:48px/1.5 sans-serif;color:white;text-shadow:0 0 0.5em black}</style><a href=https://www.youtube.com/embed/Y8Wp3dafaMQ?autoplay=1><img src=https://img.youtube.com/vi/Y8Wp3dafaMQ/hqdefault.jpg alt='Video The Dark Knight Rises: What Went Wrong? – Wisecrack Edition'><span>▶</span></a>"   frameborder="0"   allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"   allowfullscreen   title="The Dark Knight Rises: What Went Wrong? – Wisecrack Edition" ></iframe>
Comparison of a YouTube embed and an iframe with just an image in side. Barely different at all, visually.

Custom Post Types everywhere

I’m a big fan of giving myself structured data to work with. In WordPress-land, that often means Custom Post Types paired with something like the Advanced Custom Fields plugin for just the right data needed for the job.

Three CMS input screens: Add New Conference (with conference related fields), Add New Interview, and Add New Action Item.

Then I can loop over stuff and output it however I want. This isn’t that fancy, but it opens up whatever future doors I want to a lot easier.

Build your own bio

There is nothing fancy about how this works:

Bio generator showing HTML for my personal bio. Radio buttons next to it to change 1st to 3rd person, length, and code type of bio.

I literally made 18 <div> elements (3 lengths * 2 styles * 3 code types = 18) and swap between with a bit of JavaScript that calculates a class string based on the current choices, selects that class, and unhides it while hiding the rest.

$ (".bio-choices input").on("change", function () {   var lengthClass = ".bio-" + $ ("input[name=length]:checked").attr("id");   var styleClass = ".bio-" + $ ("input[name=style]:checked").attr("id");   var codeClass = ".bio-" + $ ("input[name=code]:checked").attr("id");   var selector = lengthClass + styleClass + codeClass;    $ (".bio").hide();   $ (selector).show(); });

jQuery! That’s what was already on the site, and the site also uses the jQuery version of FitVids for responsive videos — so I figured I’d just leave it all be.

If I was going to re-write these bits of the site, I’d probably rip out jQuery and use this for FitVids. Then I’d find a way to only have three bios (maybe six if I can’t find a nice way to handle first vs. third person with word swaps) and then get the rest by automatically converting the formats somehow (maybe some cloud function if I had to).

ztext.js

I used ztext for the header! It’s this kinda stuff that makes the web feel extra webby to me. I’m not sure I’d do something with quite so much movement on a site like CSS-Tricks (because people visit it more often and the time-on-site is higher). But for a site that people might land on once in a blue moon, it has the right amount of cheerful levity, I think.

Background SVG

I was stoked to see the SVG Backgrounds site get an upgrade lately. I was playing around in there and was like YES, I’m doing this.

SVG backgrounds website showing off wavy dark gray lines over black, configurable through a controls panel.

I went with a background-attachment: fixed look, which I think I like. I also added the slideout footer effect on desktop, but I’m less sold that it’s working here. It’s more fun when the background changes, and that doesn’t happen here. I’ll probably either change the background of the footer, or rip the effect out.

Filter trick for links

Some of the different sections on the site use a different primary highlight color, and I’m having the links in those sections follow that color. That might be questionable (perhaps all links should be blue) but, so far, I think it makes decent sense (they still have hover and focus styles). When you have a variety of colors and styles for interactive elements though, it often means that you have to create special alternate styles for hover and focus. That could mean crafting bespoke color alterations for each color. Not the end of the world, but I really like this little trick for interactive styles that ends up with a consistent look across all colors:

a:focus, .button:focus, a:hover, .button:hover {   filter: brightness(120%); }

Anyway! This was just a couple hours of paint on this site. Mostly because blogrolls were the CodePen Challenge that week. But I can never touch a site I haven’t in a while and just do one thing. I get sucked in and gotta do more!


The post Little Things on My Personal Site appeared first on CSS-Tricks.

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

CSS-Tricks

, , ,
[Top]

Comparing Various Ways to Hide Things in CSS

You would think that hiding content with CSS is a straightforward and solved problem, but there are multiple solutions, each one being unique.

Developers most commonly use display: none to hide the content on the page. Unfortunately, this way of hiding content isn’t bulletproof because now that content is now “inaccessible” to screen readers. It’s tempting to use it, but especially in cases where something is only meant to be visually hidden, don’t reach for it.

The fact is that there are many ways to “hide” things in CSS, each with their pros and cons which greatly depend on how it’s being used. We’re going to review each technique here and cap things off with a summary that helps us decide which to use and when.

How to spot differences between the techniques

To see a difference between different ways of hiding content, we must introduce some metrics. Metrics that we’ll use to compare the methods. I decided to break that down by asking questions focused on four particular areas that affect layout, performance and accessibility:

  1. Accessibility: Is the hidden content read by a screen reader?
  2. Document flow: Will the hidden element affect the document layout?
  3. Rendering: Will the hidden element’s box model be rendered?
  4. Event triggers: Does the element detect clicks or focus?

Now that we have our criteria out of the way, let’s compare the methods. Again, we’ll put everything together at the end in a way that we can use it as a reference for making decisions when hiding things in CSS.

Method 1: The display property

We kicked off this post with a caution about using display to hide content. And as we established, using it to hide an element means that the element is not generated at all. It’s in the DOM, but never actually rendered.

The element will still show in the markup, if you inspect the page you will be able to see the element. The box model will not generate nor appear on the page, which also applies to all its children.

And what’s more, if the element has any event listeners — say a click or hover — they won’t register at all. And as we’ve discussed already, all the content will be ignored by screen readers. Here, we have two visible buttons and one hidden with display: none. All three buttons have click events but only the two visible buttons will render and register the clicks.

Display is the only property that will affect image request firing. If an image tag (or parent element) has a display property set to none either through inline CSS or by selector, the image will be downloaded. On the other hand, if the image is applied with a background property, it won’t be downloaded.

This is the case because the parser hasn’t applied the CSS when an HTML document is parsed and it encounters an <img> tag. On the other hand, when we apply the image to an element with a background property, the image won’t be downloaded because the parser hasn’t applied the CSS where the image is called. This behavior is matched across all latest browsers. The only exception is IE 11, which will download images in both cases.

Metric Result
Is the hidden content read by a screen reader?
Will the hidden element affect the document layout?
Will the hidden element’s box model be rendered?
Does the element detect clicks or focus?

Method 2: The visibility property

If an element’s visibility property is set to hidden, then the element is “visually hidden.” Being “visually hidden” sounds a lot like what display: none does, but it’s incredibly different in that the element is generated and rendered, but invisible. This means that the element’s box model is present, giving it dimensions that continue to occupy space on the screen even though it doesn’t appear to be there.

Imagine you’re wearing an invisible cloak that makes you invisible to others, but you are still able to bump into things. You’re physically there, even if you’re invisible to the human eye.

But that’s where the differences between “visually hidden” and “not displayed” end. In fact, elements hidden with visibility and display behave the same in terms of accessibility and event triggers. Invisible elements are inaccessible to screen readers and won’t register events, as we see in the following demo that’s exactly the same as the last example, but merely swaps display: none with visibility: hidden.

Metric Result
Is the hidden content read by a screen reader?
Will the hidden element affect the document layout?
Will the hidden element’s box model be rendered?
Does the element detect clicks or focus?

Method 3: The opacity property

The opacity property only affects the visual aspect of the element. If we set an element’s opacity to zero, the element will be fully transparent. Again, it’s a lot like visibility: hidden where we’re draping an invisible cloak on the element where it’s invisible, but still physically present.

In other words, what we have is a hollow, transparent element that acts like any other element, only it’s invisible. Sounds a lot like the visibility method, right? The difference is that a fully transparent element is still accessible to a screen reader and can register events, like clicks, as we see in the following example.

Metric Result
Is the hidden content read by a screen reader?
Will the hidden element affect the document layout?
Will the hidden element’s box model be rendered?
Does the element detect clicks or focus?

Method 4: The position property

Pushing an element off-screen with absolute positioning is another way developers often hide things. Using top and left, we can push the element so far off the screen that there’s no way it will ever be seen. It’s like hiding the cookie jar outside of the house so the kids (or maybe you!) can’t find them.

“Absolute” is the key word here. If we set position to absolute, an element is taken out of the document flow which is a way of saying it no longer adheres to its natural position in the DOM. In other words, the page doesn’t reserve any space for it, which knocks the element out of order visually, positioning it to it’s nearest positioned element if there is one, or the document root if nothing else.

We take advantage of absolute positioning by taking the “hidden” element out of the document flow and offsetting it toward the top-left with values of -9999px.

.hidden {   position: absolute;   top: -9999px;   left: -9999px; }
Metric Effect
Is the hidden content read by a screen reader?
Will the hidden element affect the document layout?
Will the hidden element’s box model be rendered?
Does the element detect clicks or focus?

If the hidden element contains focusable content, the page will scroll to the element when it is in focus, creating a sudden jump.

Method 5: The “visually hidden” class

So far, the position method is the closest we’ve seen to an accessibility-friendly way to hide things in CSS. But the problem with focusable content causing sudden page jumps isn’t great. Another approach to accessible hiding combines absolute positioning, the clip property and hidden overflow. Scott O’Hara blogged it back in 2017.

.visually-hidden:not(:focus):not(:active) {   clip: rect(0 0 0 0);    clip-path: inset(50%);   height: 1px;   overflow: hidden;   position: absolute;   white-space: nowrap;    width: 1px; }

Let’s break that down.

We need to remove the element from the document flow. The best way to do this is by using position: absolute. This will remove the element, but we won’t push it off the screen.

.visually-hidden {   position: absolute; }

We can hide the element by setting the width and height property to zero. Unfortunately, that won’t work because some screen readers will ignore elements with zero width and height. What we can do is set it to the second-lowest value, 1px. That means the content will easily overflow the space, so we also need overflow: hidden to make sure it doesn’t visually spill over.

.visually-hidden {   height: 1px;   overflow: hidden;   position: absolute;   width: 1px; }

To hide that one-pixel square, we can use the CSS clipping property. It is perfect for this situation, as it doesn’t affect screen readers. The content is there but, again, is visually hidden. The thing to note is that clip was deprecated in favor of clip-path but is still needed if we need to support older versions of Internet Explorer.

.visually-hidden {   clip: rect(0 0 0 0);   clip-path: inset(50%);   height: 1px;   overflow: hidden;   position: absolute;   width: 1px; }

Another piece of the “visually hidden” class puzzle is to address smushed off-screen accessible text, an oddity that removes white-spacing between words, causing them to be read aloud like one big string of words. For example, “Welcome back home” will be read out as “Welcomebackhome.”

A simple solution to this problem is to set the white-space: nowrap:

.visually-hidden {   clip: rect(0 0 0 0);   clip-path: inset(50%);   height: 1px;   overflow: hidden;   position: absolute;   white-space: nowrap;   width: 1px; }

And, finally! The last thing to consider is to allow certain element with native focus and active sites to display when they are in focus, while continuing to prevent other elements, like paragraphs, from displaying. We can use the :not pseudo-selector for that.

.visually-hidden:not(:focus):not(:active) {   clip: rect(0 0 0 0);   clip-path: inset(50%);   height: 1px;   overflow: hidden;   position: absolute;   white-space: nowrap;   width: 1px; }
Metric Result
Is the hidden content read by a screen reader?
Will the hidden element affect the document layout?
Will the hidden element’s box model be rendered?
Does the element detect clicks or focus?

Honorable mentions

There are even more methods than the five we’ve covered. For example, the text-indent property can push text off the screen like the position method:

.hidden {   text-indent: -9999em; }

Unfortunately, this approach doesn’t jive with RTL writing modes. That makes it less adaptable than other solutions we’ve covered.

Another method is using transform to scale or move the element out of the way. It works the same — visually only — like opacity.

.hidden {   transform: scale(0); }

Let’s put everything together!

We got to a solution that will visually hide content but still be accessible. Then, should you stop using display: none? No, this is still the best way to hide an element completely (visually and accessibly).

That said, It is worth mentioning that if you want to achieve an opposite result — hide something from the screen reader, the aria-hidden="true" attribute will hide the content from screen readers, but not visually.

With that, here is a complete table that compares all of the approaches. Use it to guide your decisions on how to hide content next time you find yourself in that situation.

Metric Display Visibility Opacity Position Accessible Way
Is the hidden content read by a screen reader?
Will the hidden element affect the document layout?
Will the hidden element’s box model be rendered?
Does the element detect clicks or focus?

The post Comparing Various Ways to Hide Things in CSS appeared first on CSS-Tricks.

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

CSS-Tricks

, , , ,
[Top]

Reactive jQuery for Spaghetti-fied Legacy Codebases (or When You Can’t Have Nice Things)

I can hear you crying out now: “Why on Earth would you want to use jQuery when there are much better tools available? Madness! What sort of maniac are you?” These are reasonable questions, and I’ll answer them with a little bit of context.

In my current job, I am responsible for the care and feeding of a legacy website. It’s old. The front-end relies on jQuery, and like most old legacy systems, it’s not in the best shape. That alone isn’t the worst, but I’m working with additional constraints. For example, we’re working on a full rewrite of the system, so massive refactoring work isn’t being approved, and I’m also not permitted to add new dependencies to the existing system without a full security review, which historically can take up to a year. Effectively, jQuery is the only JavaScript library I can use, since it’s already there. 

My company has only recently come to realize that front-end developers might have important skills to contribute, so the entire front end of the app was written by developers unaware of best practices, and often contemptuous of their assignment. As a result, the code quality is wildly uneven and quite poor and unidiomatic overall.

Yeah, I work in that legacy codebase: quintessential jQuery spaghetti.

Someone has to do it, and since there will always be more legacy code in the world than greenfield projects, there will always be lots of us. I don’t want your sympathy, either. Dealing with this stuff, learning to cope with front-end spaghetti on such a massive scale has made me a better, if crankier, developer.

So how do you know if you’ve got spaghetti jQuery on your hands? One reliable code smell I’ve found is a lack of the venerable old .toggle(). If you’ve managed to successfully not think about jQuery for a while, it is a library that smooths cross-browser compatibility issues while also making DOM queries and mutations incredibly easy. There’s nothing inherently wrong with that, but direct DOM manipulation can be very hard to scale if you’re not careful. The more DOM-manipulation you write, the more defensive against DOM mutation you become. Eventually, you can find yourself with an entire codebase written that way and, combined with less-than-ideal scope management, you are essentially working in an app where all of the state is in the DOM and you can never trust what state the DOM will be in when you need to make changes; changes could swoop in from anywhere in your app whether you like it or not. Your code gets more procedural, bloating things up with more explicit instructions, trying to pull all the data you need from the DOM itself and force it into the state you need it to be in.

This is why .toggle() is often the first thing to go: if you can’t be sure whether an element is visible or not, you have to use .show() and .hide() instead. I’m not saying .show() and .hide() should be Considered Harmful™, but I’ve found they’re a good indication that there might be bigger problems afoot.

What can you do to combat this? One solution my coworkers and I have found takes a hint directly from the reactive frameworks we’d rather be using: observables and state management. We’ve all found that hand-rolling state objects and event-driven update functions while treating our DOM like a one-way dataflow template leads to more predictable results that are easier to change over time.

We each approach the problem a little differently. My take on reactive jQuery is distinctly flavored like Vue drop-in and takes advantage of some “advanced” CSS.

If you check out the script, you’ll see there are two different things happening. First, we have a State object that holds all of the values for our page, and we have a big mess of events.

var State = {   num: 0,   firstName: "",   lastName: "",   titleColor: "black",   updateState: function(key, value){     this[key] = value;              $  ("[data-text]").each(function(index, elem){       var tag = $  (elem).attr("data-tag");       $  (elem).text(State[tag]);     });          $  ("[data-color]").each(function(index, elem){       var tag = $  (elem).attr("data-tag");       $  (elem).attr("data-color", State[tag]);     });   } };

I’ll admit it, I love custom HTML attributes, and I’ve applied them liberally throughout my solution. I’ve never liked how HTML classes often do double-duty as CSS hooks and JavaScript hooks, and how if you use a class for both purposes at once, you’ve introduced brittleness into your script. This problem goes away completely with HTML attributes. Classes become classes again, and the attributes become whatever metadata or styling hook I need.

If you look at the HTML, you’ll find that every element in the DOM that needs to display data has a data-tag attribute with a value that corresponds to a property in the State object that contains the data to be displayed, and an attribute with no value that describes the sort of transformation that needs to happen to the element it’s applied to. This example has two different sorts of transformations, text and color.

<h1 data-tag="titleColor" data-color>jDux is super cool!</h1>

On to the events. Every change we want to make to our data is fired by an event. In the script, you’ll find every event we’re concerned about listed with its own .on() method. Every event triggers an update method and sends two pieces of information: which property in the State object that needs to be updated, and the new value it should be set to.

$  ("#inc").on("click", function(){   State.updateState("num", State.num + 1) });  $  ("#dec").on("click", function(){   State.updateState("num", State.num - 1) });  $  ("#firstNameInput").on("input", function(){   State.updateState("firstName", $  (this).val() ) });  $  ("#lastNameInput").on("input", function(){   State.updateState("lastName", $  (this).val() ) });  $  ('[class^=button]').on("click", function(e) {   State.updateState('titleColor', e.target.innerText); });

This brings us to State.updateState(), the update function that keeps your page in sync with your state object. Every time it runs, it updates all the tagged values on the page. It’s not the most efficient thing to redo everything on the page every time, but it’s a lot simpler, and as I hope I’ve already made clear, this is an imperfect solution for an imperfect codebase.

$  (document).ready(function(){   State.updateState(); });

The first thing the update function does is update the value according to the property it receives. Then it runs the two transformations I mentioned. For text elements, it makes a list of all data-text nodes, grabs their data-tag value, and sets the text to whatever is in the tagged property. Color works a little differently, setting the data-color attribute to the value of the tagged property, and then relies on the CSS, which styles the data-color properties to show the correct style.

I’ve also added a document.ready, so we can run the update function on load and display our default values. You can pull default values from the DOM, or an AJAX call, or just load the State object with them already entered as I’ve done here.

And that’s it! All we do is keep the state in the JavaScript, observe our events, and react to changes as they happen. Simple, right?

What’s the benefit here? Working with a pattern like this maintains a single source of truth in your state object that you control, you can trust and you can enforce. If you ever lose trust that your DOM is correct, all you need to do is re-run the update function with no arguments and your values become consistent with the state object again.

Is this kind of hokey and primitive? Absolutely. Would you want to build an entire system out of this? Certainly not. If you have better tools available to you, you should use them. But if you’re in a highly restrictive legacy codebase like I am, try writing your next feature with Reactive jQuery and see if it makes your code, and your life, simpler.


The post Reactive jQuery for Spaghetti-fied Legacy Codebases (or When You Can’t Have Nice Things) appeared first on CSS-Tricks.

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

CSS-Tricks

, , , , , , ,
[Top]

Exciting Things on the Horizon For CSS Layout

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

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

Direct Link to ArticlePermalink

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

CSS-Tricks

, , ,
[Top]

SVG, Favicons, and All the Fun Things We Can Do With Them

Favicons are the little icons you see in your browser tab. They help you understand which site is which when you’re scanning through your browser’s bookmarks and open tabs. They’re a neat part of internet history that are capable of performing some cool tricks.

One very new trick is the ability to use SVG as a favicon. It’s something that most modern browsers support, with more support on the way.

Here’s the code for how to add favicons to your site:

<link rel="icon" type="image/svg+xml" href="/favicon.svg"> <link rel="alternate icon" href="/favicon.ico"> <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#ff8a01">

If a browser doesn’t support a SVG favicon, it will ignore the first link element declaration and continue on to the second. This ensures that all browsers that support favicons can enjoy the experience. 

You may also notice the alternate attribute value for our rel declaration in the second line. This programmatically communicates to the browser that the favicon with a file format that uses .ico is specifically used as an alternate presentation.

Following the favicons is a line of code that loads another SVG image, one called safari-pinned-tab.svg. This is to support Safari’s pinned tab functionality, which existed before other browsers had SVG favicon support. There’s additional files you can add here to enhance your site for different apps and services, but more on that in a bit.

Here’s more detail on the current level of SVG favicon support:

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

Desktop

Chrome Firefox IE Edge Safari
80 41 No 80 TP

Mobile / Tablet

Android Chrome Android Firefox Android iOS Safari
80 No No 13.4

Why SVG?

You may be questioning why this is needed. The .ico file format has been around forever and can support images up to 256×256 pixels in size. Here are three answers for you.

Ease of authoring

It’s a pain to make .ico files. The file is a proprietary format used by Microsoft, meaning you’ll need specialized tools to make them. SVG is an open standard, meaning you can use them without any further tooling or platform lock-in.

Future-proofing

Retina? 5k? 6k? When we use a resolution-agnostic SVG file for a favicon, we guarantee that our favicons look crisp on future devices, regardless of how large their displays get

Performance

SVGs are usually very small files, especially when compared to their raster image counterparts — even more-so if you optimize them beforehand. By only using a 16×16 pixel favicon as a fallback for browsers that don’t support SVG, we provide a combination that enjoys a high degree of support with a smaller file size to boot. 

This might seem a bit extreme, but when it comes to web performance, every byte counts!

Tricks

Another cool thing about SVG is we can embed CSS directly in it. This means we can do fun things like dynamically adjust them with JavaScript, provided the SVG is declared inline and not embedded using an img element.

<svg  version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">   <style>     path { fill: #272019; }   </style>   <!-- etc. --> </svg>

Since SVG favicons are embedded using the link element, they can’t really be modified using JavaScript. We can, however, use things like emoji and media queries.

Emoji

Lea Verou had a genius idea about using emoji inside of SVG’s text element to make a quick favicon with a transparent background that holds up at small sizes.

In response, Chris Coyier whipped up a neat little demo that lets you play around with the concept.

Dark Mode support

Both Thomas Steiner and Mathias Bynens independently stumbled across the idea that you can use the prefers-color-scheme media query to provide support for dark mode. This work is built off of Jake Archibald’s exploration of SVG and media queries.

<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg">   <style>     path { fill: #000000; }     @media (prefers-color-scheme: dark) {       path { fill: #ffffff; }     }   </style>   <path d="M111.904 52.937a1.95 1.95 0 00-1.555-1.314l-30.835-4.502-13.786-28.136c-.653-1.313-2.803-1.313-3.456 0L48.486 47.121l-30.835 4.502a1.95 1.95 0 00-1.555 1.314 1.952 1.952 0 00.48 1.99l22.33 21.894-5.28 30.918c-.115.715.173 1.45.768 1.894a1.904 1.904 0 002.016.135L64 95.178l27.59 14.59c.269.155.576.232.883.232a1.98 1.98 0 001.133-.367 1.974 1.974 0 00.768-1.894l-5.28-30.918 22.33-21.893c.518-.522.71-1.276.48-1.99z" fill-rule="nonzero"/> </svg>

For supporting browsers, this code means our star-shaped SVG favicon will change its fill color from black to white when dark mode is activated. Pretty neat!

Other media queries

Dark mode support got me thinking: if SVGs can support prefers-color-scheme, what other things can we do with them? While the support for Level 5 Media Queries may not be there yet, here’s some ideas to consider:

Mockup of four SVG favicon treatments. The first treatment is a pink star with a tab title of, “SVG Favicon.” The second treatment is a hot pink star with a tab title of, “Light Level SVG Favicon.” The third treatment is a light pink star with a tab title of, “Inverted Colors SVG Favicon.” The fourth treatment is a black pink star with a tab title of, “High Contrast Mode SVG Favicon.” The tabs are screen captures from Microsoft Edge, with the browser chrome updating to match each specialized mode.
A mockup of how these media query-based adjustments could work.

Keep it crisp

Another important aspect of good favicon design is making sure they look good in the small browser tab area. The secret to this is making the paths of the vector image line up to the pixel grid, the guide a computer uses to turn SVG math into the bitmap we see on a screen. 

Here’s a simplified example using a square shape:

A crisp orange square on a white background. There is also a faint grid of gray horizontal and vertical lines that represent the pixel grid. Screenshot from Figma.

When the vector points of the square align to the pixel grid of the artboard, the antialiasing effect a computer uses to smooth out the shapes isn’t needed. When the vector points aren’t aligned, we get a “smearing” effect:

A blurred orange square on a white background. There is also a faint grid of gray horizontal and vertical lines that represent the pixel grid. Screenshot from Figma.

A vector point’s position can be adjusted on the pixel grid by using a vector editing program such as Figma, Sketch, Inkscape, or Illustrator. These programs export SVGs as well. To adjust a vector point’s location, select each node with a precision selection tool and drag it into position.

Some more complicated icons may need to be simplified, in order to look good at such a small size. If you’re looking for a good primer on this, Jeremy Frank wrote a really good two-part article over at Vidget.

Go the extra mile

In addition to favicons, there are a bunch of different (and unfortunately proprietary) ways to use icons to enhance its experience. These include things like the aforementioned pinned tab icon for Safari¹, chat app unfurls, a pinned Windows start menu tile, social media previews, and homescreen launchers.

If you’re looking for a great place to get started with these kinds of enhancements, I really like realfavicongenerator.net.

Icon output from realfavicongenerator.net arranged in a grid using CSS-Trick’s logo. There are two rows of five icons: android-chrome-192x192.png, android-chrome-384x384.png, apple-touch-icon.png, favicon-16x16.png, favicon-32x32.png, mstile-150x150.png, safari-pinned-tab.svg, favicon.ico, browserconfig.xml, and site.webmanifest.
It’s a lot, but it guarantees robust support.

A funny thing about the history of the favicon: Internet Explorer was the first browser to support them and they were snuck in at the 11th hour by a developer named Bharat Shyam:

As the story goes, late one night, Shyam was working on his new favicon feature. He called over junior project manager Ray Sun to take a look.

Shyam commented, “This is good, right? Check it in?”, requesting permission to check the code into the Internet Explorer codebase so it could be released in the next version. Sun didn’t think too much of it, the feature was cool and would clearly give IE an edge. So he told Shyam to go ahead and add it. And just like that, the favicon made its way into Internet Explorer 5, which would go on to become one of the largest browser releases the web has ever seen.

The next day, Sun was reprimanded by his manager for letting the feature get by so quickly. As it turns out, Shyam had specifically waited until later in the day, knowing that a less experienced Program Manager would give him a pass. But by then, the code had been merged in. Incidentally, you’d be surprised just how many relatively major browser features have snuck their way into releases like this.

From How We Got the Favicon by Jay Hoffmann

I’m happy to see the platform throw a little love at favicons. They’ve long been one of my favorite little design details, and I’m excited that they’re becoming more reactive to user’s needs. If you have a moment, why not sneak a SVG favicon into your project the same way Bharat Shyam did way back in 1999. 


¹ I haven’t been able to determine if Safari is going to implement SVG favicon support, but I hope they do. Has anyone heard anything?

The post SVG, Favicons, and All the Fun Things We Can Do With Them appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

15 Things to Improve Your Website Accessibility

This is a really great list from Bruce. There is a lot of directly actionable stuff here. Send it around to your team and make it something that you all go through together.

Here’s a little one that prodded me to finally fix…

Most screen readers allow the user to quickly see a list of links on a page [..] However, if every link has text saying “Click here” or “Read more”, with nothing else to distinguish them, this is useless. The easiest way to solve this is simply to write unique link text, but if that isn’t possible, you can over-ride the link text for assistive technology by using a unique aria-label attribute on each link.

I had links like that right here on CSS-Tricks. Some of them are automatically created by WordPress itself, not something I hand-coded into a template. When you show the_excerpt of a post, you get a “read more” link automatically, and aside from getting your hands dirty with some filters, you don’t have that much control over it.

DevTools showing the DOM of a "read more" link with no context.

Fortunately, I already use a cool plugin called Advanced Excerpt. I poked into the settings to see if I could do something about injecting the post title in there somehow. Lookie lookie:

A setting for Advanced Excerpt that does screen reader links.

That screen-reader-text class is exactly what I already used for that kind of stuff, so it was a one-click fix!

Much nicer DOM now for those links:

Direct Link to ArticlePermalink

The post 15 Things to Improve Your Website Accessibility appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]

Making Things Better: Redefining the Technical Possibilities of CSS

(This is a sponsored post.)

Robin recently lamented the common complaint that CSS is frustrating. There are misconceptions about what it is and what it does. There are debates about what kind of language it is. There are even different views on where it should be written.

Rachel Andrew has a new talk from An Event Apart DC 2019 available that walks us back; back to the roots of the issues we used to have with CSS and the “hacks” we used to overcome them. CSS has changed a lot over the past few years and, while those changes have felt complex and confusing at times, they are designed to solve what we have always wanted CSS to do.

The full hour it takes to watch the talk is well worth the time. Here are a few nuggets that stood out. First off, some de-bunking of common CSS complaints:

  • You never know how tall anything is on the web. Floats never solved this because they only bring things next to each other instead of knowing about the items around them. New layout methods, including CSS Grid and Flexbox, actually look at our elements and help them behave consistently.
  • Flexbox is weird and unintuitive. It’s not the layout method you might think it is. If we view it as a way to line things up next to each other, it’s going to feel weird and behavior weirdly as well. But if we see it for what it is – a method that looks at differently sized elements and returns the most logical layout – it starts to make sense. It assigns space, rather than squishing things into a box.

Rachel continues by giving us a peek into the future of what CSS wants to do for us:

  • CSS wants to avoid data loss. New alignment keywords like safe and unsafe will give us extra control to define whether we want CSS to aggressively avoid content that’s unintentionally hidden or allow it to happen.
.container {   display: flex;   flex-direction: column;   /* Please center as long as it doesn't result in overflow */   align-items: safe center; }
  • CSS wants to help us get real with overflow. Themin-content and max-content keywords make it possible to create boxes that are wide enough for the content but not wider, and boxes that are as big as the content can be.
.container {   width: min-content; /* Allow wrapping */ }
  • CSS wants to lay things out logically. The web is not left-to-right. Grid and Flexbox quietly introduced a way of thinking start-to-end that is direction agnostic. That has brought about a new specification for Logical Properties and Values.
  • CSS wants to make content more portable. CSS Regions let us flow content from one element into another. While it’s probably a flawed comparison, it’s sorta like the pipes in old school Mario Bros. games where jumping in one pipe at one location will plop your character out of another pipe in another location… but we get to define those sources ourselves and without angry plants trying to eat us along the way.

Anyway, these are merely scratching the surface of what Rachel covers in her talk. It’s a good reminder that An Event Apart has an entire library of valuable talks from amazing speakers and that attending an AEA event is an invaluable experience worth checking out. Rachel’s talk was from last year’s Washington D.C. event and, as it turns out, the very next event is taking place there this April 13-15. If you can’t make that one, there are several others throughout the year across the United States.

Oh, and of course we have a discount code for you! Use AEACP for $ 100 off any show.

Direct Link to ArticlePermalink

The post Making Things Better: Redefining the Technical Possibilities of CSS appeared first on CSS-Tricks.

CSS-Tricks

, , , , ,
[Top]

Things you can do with a browser in 2020

I edit a good amount of technical articles about the web, and there is a tendency for authors to be super broad in their opening sentence, like “What we’re able to do on the web has expanded greatly over the years.”

I tend to remove stuff like that because it usually doesn’t serve the article well, even though I understand the sentiment.

Just look at Luigi De Rosa’s list here. I’d bet a lot of you didn’t know the browser could do all that stuff — push notifications! Native sharing menus! Picture-in-picture!

It’s mostly JavaScript stuff, a little CSS, and notably absent: anything in HTML.

Direct Link to ArticlePermalink

The post Things you can do with a browser in 2020 appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

“All these things are quite easy to do, they just need somebody to sit down and just go through the website”

I saw a video posted on Twitter from Channel 5 News in the UK (I have no idea what the credibility of them is, it’s an ocean away from me) with anchor Claudia Liza asking Glen Turner and Kristina Barrick questions about website accessibility.

Apparently, they often post videos with captions, but this particular video doesn’t (ironically). So, I’ve transcribed it here as I found them pretty well-spoken.

[Claudia Liza]: … you do have a visual impairment. How does that make it difficult for you to shop online?

[Glen Turner]: Well, I use various special features on my devices to shop online to make it easier. So, I enlarge the text, I’ll invert the colors to make the background dark so that I don’t have glare. I will zoom in on pictures, I will use speech to read things to me because it’s too difficult sometimes. But sometimes websites and apps aren’t designed in a way that is compatible with that. So sometimes the text will be poorly contrasted so you’ll have things like brown on black, or red on black, or yellow on white, something like that. Or the menu system won’t be very easy to navigate, or images won’t have descriptions for the visually impaired because images can have descriptions embedded that a speech reader will read back to them. So all these various factors make it difficult or impossible to shop on certain websites.

[Claudia Liza]: What do you need retailers to do? How do they need to change their technology on their websites and apps to make it easier?

It’s quite easy to do a lot of these things, really. Check the colors on your website. Make sure you’ve got light against dark and there is a very clear distinctive contrast. Make sure there are descriptions for the visually impaired. Make sure there are captions on videos for the hearing impaired. Make sure your menus are easy to navigate and make it easy to get around. All these things are quite easy to do, they just need somebody to sit down and just go through the website and check that it’s all right and consult disabled people as well. Ideally, you’ve got disabled people in your organization you employ, but consult the wider disabled community as well. There is loads of us online there is loads of us spread all over the country. There is 14 million of us you can talk to, so come and talk to us and say, “You know, is our website accessible for you? What can we do to improve it?” Then act on it when we give you our advice.

[Claudia Liza]: It makes sense doesn’t it, Glen? It sounds so simple. But Christina, it is a bit tricky for retailers. Why is that? What do other people with disabilities tell you?

So, we hear about content on websites being confusing in the way it’s written. There’s lots of information online about how to make an accessible website. There’s a global minimum legal standard called WCAG and there’s lot of resources online. Scope has their own which has loads of information on how to make your website accessible.

I think the problem really is generally lack of awareness. It doesn’t get spoken about a lot. I think that disabled consumers – there’s not a lot of places to complain. Sometimes they’ll go on a website and there isn’t even a way to contact that business to tell them that their website isn’t accessible. So what Scope is trying to do is raise the voices of disabled people. We have crowdsourced a lot of people’s feedback on where they experience inaccessible websites. We’re raising that profile and trying to get businesses to change.

[Claudia Liza]: So is it legal when retails aren’t making their websites accessible?

Yeah, so, under the Equality Act 2010, it’s not legal to create an inaccessible website, but what we’ve found is that government isn’t generally enforcing that as a law.

[Claudia Liza]: Glenn, do you feel confident that one day you’ll be able to buy whatever you want online?

I would certainly like to think that would be the case. As I say, you raise enough awareness and get the message out there and alert business to the fact that there is a huge consumer market among the disabled community, and we’ve got a 274 billion pound expenditure a year that we can give to them. Then if they are aware of that, then yeah, hopefully they will open their doors to us and let us spend our money with them.

The post “All these things are quite easy to do, they just need somebody to sit down and just go through the website” appeared first on CSS-Tricks.

CSS-Tricks

, , , , , , , , , , ,
[Top]