Tag: Things

Top Things You Didn’t Know You Could Do With Netlify CLI

(This is a sponsored post.)

First things first, if you didn’t know Netlify had a CLI, they do.  One of my favorite things about it running the command netlify dev on nearly any static-site generator project is seeing it detect what it should be doing and spinning the site up in a dev server for you. But not just any dev server, a dev server that replicates the Netlify environment, meaning things like running your serverless functions and making your environment variables available.

Here are five more things you can do with it that you might not realize.

1) Create a new site from a template

That’s right, spin up a new site by typing a single command and walking through the steps. Try it:

netlify sites:create-template

There is a shorthand to the CLI as well! Try the above as ntl sites:create-template

As Charlie Gerard writes in a blog post about this:

At the moment, our templates include a Gatsby and Hugo starter with the Netlify CMS, as well as a Next.js starter. 

2) Manage your environment variables 

The netlify env command, now in Beta, allows you to control environment variables. You can list them out with netlify env:list, get and set (and unset) them. My favorite: move a whole set of them from one site to another like netlify env:migrate --to <to-site-id>.

3) Test serverless functions

By virtue of spinning up your site locally with the Netlify CLI, your serverless functions will run. You can test that they are working and inspect the network traffic and such that way. But the CLI can help you as well, the netlify functions command is capable of testing functions at the command line level. For example, netlify functions:invoke can trigger a function with simulated data.

4) Live stream your Dev environment

Here’s Melanie Crissey on the Netlify Blog about this:

While Netlify’s collaborative Deploy Previews are our go-to for asynchronous feedback, sometimes you need to drop everything and pair on an issue together. That’s when Netlify Live really shines.

For example, just last week, our team was working quickly to debug some funky edge case issues with authentication for the Your Year on Netlify project. Zach Leatherman, who was working on the fix, spun up a local version of the app with Netlify Live. Within minutes, he was able to see the logs, identify the issue, and make a few changes. Meanwhile, I was able to test out the fix before it was ever deployed—without pulling down a copy of his latest version from a repo. Netlify CLI to the rescue and problem solved!

Remember how I mentioned you spin up a dev environment locally with netlify dev? The trick here is to do netlify dev --live. So rather than a localhost URL that only you would be able to see, you’ll get a special netlify.live URL that the world can see.

5) Run netlify switch to switch between different Netlify accounts, like from your personal side project to a work project

You literally auth with the CLI (netlify login, imagine that), so that you can act on behalf of your own Netlify account. Deploy sites and whatnot. But it’s perfectly reasonable that you have multiple Netlify accounts (like work and personal). Running netlify switch makes it trivial to move between accounts.

BONUS!

This video is 50 seconds long and shows how you can go from having some static files locally to a deployed with the CLI:


Top Things You Didn’t Know You Could Do With Netlify CLI originally published on CSS-Tricks. You should get the newsletter.

CSS-Tricks

, , , , ,

Make Joyful Things

Everything kind of sucks right now. Things—generally—feel bad. Setting aside the broader realities of a global pandemic and rampant social injustices, we’re watching the identity of the web platform, an intrinsically free and open medium of creative expression, co-opted for the “Web 3.0” grift built on artificial scarcity and an accelerating climate crisis.

Websites (mostly) look kind of the same. The proliferation of frameworks, vector design tools, data-driven design and an imperative to maximize business value (oh dear, it was capitalism all along) has led to a status quo of design by default. Websites having their own, consistent, portable UX language that helps users quickly comprehend new sites is great, but embracing that language is a trade-off, and design doldrums is the cost.

What if it didn’t have to be this way? What if we decided to create joy with our work? After all, in a profoundly dark time for many, making someone smile or laugh with your work is a special thing. Shouldn’t we try to do that if we can?

“Okay, you got me, but how?” I hear you ask.

Well, this is how:

The web community is bursting with folks who create joy with their work. Let’s look at how they do it.

Unexpected interactions

Did you know that the web is an interactive medium? I know, weird, right? People get an “oooh neat” feeling when something responds to them. Cats knock stuff off shelves, people hover and click on stuff. It’s simple biology (probably; I’m not a biologist).

Cassie Evans puts the “virtuoso” in SVG (the V stands for virtuoso) (it does not) with this animated portrait on her personal site. I absolutely adore how it tracks the cursor in a natural-feeling way, and I love how her expression changes when you hover an interactive element.

I loved this little hover interaction from Josh Comeau’s site. I thought that there might be a hidden interaction in this 3D illustration, but I was surprised to see the background react to my cursor. As far as I can tell, it doesn’t serve a “purpose” and it cost me a few precious moments I could have spent Engaging With Content, but it made me smile.

This little pop-up book-esque pull tab on Lynn Fisher’s site is lovely. I’m sure a click or scroll would be easier to implement and get the job done, but this is special. It’s different, it’s unexpected. It’s fun. Every single iteration of her site is excellent, so I encourage you to check out her archive.

Animation

We’re finally at the place where motion is baked into design systems and considered (nearly) as important as your typefaces and colors. Despite this, we can still use animation to elevate an interaction from neat to joyful.

Another banger from Josh Comeau: this little interaction on his blog’s Like button. It could just be a ❤️ icon, sure, but it’s full of delightful personality, with lots of appeal and secondary action. The bouncy easing curve and the exuberant expression creates appeal, while the +1 and confetti at the end add some welcome secondary action. This even reinforces the experience because it encourages folks to hit that little button. Go try it out, there are also some wonderful little sound effects!

3D

Between WebGL and CSS 3D, pushing the web beyond two dimensions has been possible for ages. Good news is that it’s still a specialized skill and sometimes a pain in the ass, so it’s still rare. Even after “3D illustration” became all the rage, interactive 3D elements are still a great way to inject a little personality.

lepuzz.com is a joyful website throughout, but I especially love the spinning product images you get on hover.

Internet cryptid “Henry” “Desroches” adds a bit of personality with these animated 3D flags that appear when hovering over his case studies. He uses a noise texture to displace vertices on a plane, which creates this lovely, soothing effect.

Don’t turn this into a listicle, let’s wrap this up

  • Break the rules!
  • Use weird colors!
  • Put animations and interactions where they don’t belong!
  • Use sound effects!

The web is as much a cultural artifact as it is a platform for tricking people into looking at ads. We have the power to make people happy with our work; to share the love in a literal sense.

Understand that prioritizing joy will have a cost. Like everything else involved with making things, its a tradeoff. It might make someone’s computer fans turn on which will make some people—who are not in the pocket of Big Fan—extremely upset. It might be slower, and less usable for folks on slower devices. Creating joy will take time that you can’t spend on maximizing key metrics and synergizing upward overflow; mitigating the negative impacts of these tradeoffs will eat yet more time. There’s a reason that almost all of the above examples are from personal sites and not big Brands, after all.

What if making somebody smile is worth it though? What if it’s worth the cost? In a lot of ways, we’re living in shitty times. It’s worth giving up a little to take your shot at making someone’s day. L

CSS-Tricks

,
[Top]

Dock Life: Using Docker for All The Things!

I think if you’re a DevOps person in any capacity, the utility of Docker is very clear. Your things run in containers that are identical everywhere. Assuming Docker is working/running, the code will execute in a reliably consistent way whether that is Docker running on some developer’s computer, or a sky computer. The (massive) appeal there is that bugs will happen consistently. “Production-only” bugs become a thing of the past. There are other benefits, too, like shipping a dev environment to a team of developers that is entirely consistent, even across platforms, rather than battling with individual developers computers.

So… great? Use it all the time for everything? The stopper there is that it’s complicated, and web dev is already friggin complicated and it often just feels like too much. Andrew Welch, however, makes the case that you don’t have to learn Docker super deeply in order to use it:

Dock­er is a devops tool that some peo­ple find intim­i­dat­ing because there is much to learn in order to build things with it. And while that’s true, it’s actu­al­ly quite sim­ple to start using Dock­er for some very prac­ti­cal and use­ful things, by lever­ag­ing what oth­er peo­ple have created.

Fair point. I don’t deeply understand most of the technology I use, but I can still use it.

While I run Docker all day for CodePen’s fancy dev environment, that’s what my use is limited to. I don’t reach for it like Andrew does for everything. But I can see how it might feel liberating having all that isolation between projects. One of my favorite of points that Andrew makes is:

Switch­ing to a new com­put­er is easy. You don’t have to spend hours metic­u­lous­ly recon­fig­ur­ing your shiny new Mac­Book Pro with all the inter­con­nect­ed tools & pack­ages you need.

I find myself bopping around between computers fairly often for various odd reasons, and being able to make the switch with minimal fussing around is appealing.

To Shared LinkPermalink on CSS-Tricks

CSS-Tricks

, , , ,
[Top]

System *Things

I think we’re all largely aware of named colors in CSS:

color: OldLace; background: rebeccapurple;

I guess you’d just call those “named colors” in CSS.

Those aren’t the only kind of named colors there are though. Some of them are a bit more fluid. Jim Nielsen was blowin’ minds the other day when he blogged about System Colors.

What I need is a way to say “hey browser, for my dropdown, use the same black (or white if in light mode) that you’re using for the background color of the document”. I need access to a variable of sorts that references the exact “black” the browser is using.

Then, via Thomas Steiner, I discovered there are literally CSS system colors. These aren’t colors that are (or at least attempt to be) the same across all browsers, but they are allowed to be set by “choices made by the user, the browser, or the OS.” So for example, Canvas is the “background of application content or documents.” Case in point: the background-color for dark mode is #1e1e1e in Safari and #121212 in Chrome. If you like that, meaning you’re leaning into what the browser thinks is a good color for things, then you can now access it through that Canvas keyword.

System colors! There are a bunch of them.

  • Canvas
  • CanvasText
  • LinkText
  • VisitedText
  • ActiveText
  • ButtonFace
  • ButtonText
  • ButtonBorder
  • Field
  • FieldText
  • Highlight
  • HighlightText
  • Mark
  • MarkText
  • GrayText

Not only do they change across browsers, they change when toggling between dark and light mode as long as you have CSS in place to support them…

html {   color-scheme: light dark; }

You’ll see them change when modes change. And you don’t have to use them for what they were designed for, I suppose:

So those are the system colors, but you can see right in that Pen that I’ve also used a system font: system-ui. Same vibe! It’s purposely fluid. It’s not going to be the same typeface across browsers and operating systems. Jim also covered this a while back. We used to replicate the idea with a big long stack of named fonts, but now CSS helps with it (in supporting browsers).

There are a bunch of them specced:

  • serif
  • sans-serif
  • monospace
  • system-ui
  • cursive
  • fantasy
  • emoji
  • math
  • fangsong
  • ui-serif
  • ui-sans-serif
  • ui-monospace
  • ui-rounded

Support seems scattered. For example, I could set this:

p {   font-family: ui-monospace, system-ui, fantasy; }

On my Mac, in Safari, I’d get SF Mono (ui-monospace). But in Chrome, ui-monospace doesn’t work so it would fall back to SF Pro (system-ui). In Firefox neither ui-monospace or system-ui work and I’d get Papyrus (fantasy). So font stacks are still important. It’s just funny to think about because these new system font keywords are almost like font stacks in and of themselves.

So there are system colors and system fonts — doesn’t that beg the question of what other system things there are?

Well, there are named font weights — like how font-weight: bold; is the same as 700, and bolder is just a bit more bold than the parent. But that doesn’t feel like a system-level thing where the system would want to take hold of that and do different things. But hey, maybe.

There are also named font sizes, like font-size: xx-small;. I could see systems wanting to get their hands on those values and adjust them to sizes that make sense contextually, but in a quick glance (comparing Chrome and iOS Safari), they compute to the same sizes.

Those named font size values don’t travel, either. I can’t do margin: large;. Well, I can, but it doesn’t do anything. So no real universal system sizes.

What about system icons? We do kinda have those in the form of emoji! We use the emoji knowing that different systems will render it differently and are generally fine with that as we know it will look consistent with that user’s platform.

The “Blue Book” emoji (via Emojipedia)

We could sort of think of inputs as “system inputs.” We know different browsers and platforms render input controls in very different ways, and that is how the spec intends it. To each their own.


The post System *Things appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

,
[Top]

The Things I Add to Tailwind CSS Right Out of the Box

In every project where I use Tailwind CSS, I end up adding something to it. Some of these things I add in every single project. I’ll share these with you, but I’m also curious what y’all are adding to your tailwind.css files.

I’ll start with myself. In each project:

  • I define -webkit-tap-highlight-color.
  • I add a bottom padding set to env(safe-area-inset-bottom).
  • I dress up unordered lists with interpuncts.

Allow me to elaborate on all three.

-webkit-tap-highlight-color

Android highlights taps on links. I’m not a fan because it obscures the element, so I turn it off for a nicer experience.

@layer base {   html {     -webkit-tap-highlight-color: transparent;   } }

@layer is a Tailwind directive. It helps avoid specificity issues by telling Tailwind which “bucket” contains a set of custom styles. It’s like pretending the cascade doesn’t exist, so there’s less to worry about when it comes to ordering CSS.

Simply removing the tap highlight color might trigger an accessibility issue since that hides an interactive cue. So, if you go this route, it’s probably a good idea (and I’m still looking for research on this if you have it) to enable :active to define provide some response to those actions. Chris has a snippet for that.

env(safe-area-inset-bottom)

This utility class handles the bottom bar on newer iPhones without the “Home” button. Without it, some elements can fall under the bar, making them unreadable and tough to tap.

@layer utilities {   .pb-safe {     padding-bottom: env(safe-area-inset-bottom);   } }

Interpuncts

I love using interpuncts with unordered lists. I won’t penalize you for looking that up. We’re basically talking about the bullet points in unordered lists. Tailwind removes them by default via Normalize. I smuggle interpuncts into each and every one of my projects.

Here’s how I go about it:

@layer utilities {   .list-interpunct > li::before {     content: '・';     display: inline-block;     float: left;     margin: 0 0 0 -0.9em;     width: 0.9em;   }    @media (min-width: 992px) {    .list-interpunct > li::before {       margin: 0 0 0 -1.5em;       width: 1.5em;     }   } }

We also now have ::marker to do the same thing and it’s a little easier to work with. Why am I not using it? I prefer to have control of the spacing between interpuncts and the text and I just don’t get that with ::marker. But that’s just me!

Now it’s your turn

Alright, I shared what I add to all of my Tailwind projects, so now it’s your turn. What do you add to Tailwind in your projects? Is there something you can’t do without? Let me know in the comments! I’d love ideas to start incorporating into other projects.


The post The Things I Add to Tailwind CSS Right Out of the Box appeared first on CSS-Tricks.

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

CSS-Tricks

, ,
[Top]

Things You Can Do With CSS Today

Some nice coverage from Andy about CSS things that are truly new. If you haven’t looked at new things in CSS in, say, a year, I’d bet pretty much all of this will be new to you. A lot of it is cutting-edge enough that you might not be able to get it into projects immediately, but that gap is getting pretty short these days. Rough guess, I’d say a year and we’ll be using all this stuff without much thought.

  • Masonry layout (e.g. grid-template-rows: masonry;) which I think was a terribly clever way to approach this long-awaited feature..
  • The :is selector which makes certain selectors way less obnoxious to write (e.g. article :is(h1, h2, h3):not(:first-child)). This makes me wonder why we never had such a thing in Sass that helped with that.
  • Functions like min(), max(), and clamp(), and I think the best practices and clever uses for them are just shaking out. Fluid type is the most obvious and useful example, but only scratches the surface.
  • Units like ch and ex. I really like max-width: 70ch;. There’s a general bit of typography advice that line length should be between 45 and 75 characters long (I made a bookmarklet to test it once), so rather than forcing that with some abstractly related width, you use the actual width of characters as the width.
  • Fancy text-decoration (e.g. text-decoration-thickness: 0.5rem;) meaning we can thicken up an underline without giving up the usefulness that is text-decoration-skip-ink like we would if we had to resort to a border.)

Direct Link to ArticlePermalink


The post Things You Can Do With CSS Today appeared first on CSS-Tricks.

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

CSS-Tricks

,
[Top]

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

, , , , ,
[Top]

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]