Violet Peña has shared her recommendations for using CSS Grid. They basically boil down to these high-level points:
Use names instead of numbers for setting up our grid columns.
fr should be our flexible unit of choice.
We don’t really need a grid system anymore.
Although this is all great advice and Violet provides a few examples to support her recommendations, I particularly like what she has to say about learning CSS Grid:
“Learning” CSS Grid requires developing working knowledge of many new properties that don’t just describe one aspect of appearance or behavior, but feed into a completely new layout system. This system includes around 18 properties which use paradigms and syntax rarely (or never) seen anywhere else in the CSS spec.
This means that CSS Grid has a pretty high skill floor — a developer needs to learn and internalize lots of new information in order to be effective with it. Once you’re above that skill floor, Grid is an amazing ally in layout creation. Below that skill floor, Grid is an encumbrance. You wonder why you’re bothering to use it at all, since it seems to require lots of additional work for little reward.
In this post, I want to help you overcome that skill floor by showing you the most effective ways to leverage the Grid spec.
Also this post reminded me that, although I’m not sure why, I tend to avoid naming my grid columns up. Like in this bit of code that Violet walks us through:
Now we can use the sidebar or content names when we define our grid-column like this:
.content { grid-column: content;
}
I really like that! It seems super easy to read and if we wanted to change the size of our .content, class then it only requires going back to where the grid is defined in the first place. Anyway, I’ll be sure to name my grid columns from here on out.
Web animation is one of the factors that can strongly enhance your website’s look and feel. Sadly, unlike mobile apps, there aren’t as many websites using animation to their benefit as you would think. We don’t want to count yours among those, so this article is for you and anyone else looking for ways to use animation for a better user experience! Specifically, we’re going to learn how to make web interactions delightful using CSS animations.
Before we move ahead, it’s worth mentioning that I’m going to assume you have at least some familiarity with modern front-end frameworks and a basic understanding of CSS animations. If you don’t, then no fear! CSS-Tricks has a great guides on React and Vue, as well as a thorough almanac post on the CSSanimation property.
Good? OK, let’s talk about why we’d want to use animation in the first place and cover some baseline information about CSS animations.
Why would we to animate anything?
We could probably do an entire post on this topic alone. Oh, wait! Sarah Drasner already did that and her points are both poignant and compelling.
But, to sum things up based on my own experiences:
Animations enhance the way users interact with an interface. For example, smart animations can reduce cognitive load by giving users better context between page transitions.
They can provide clear cues to users, like where we want them to focus attention.
Animations serve as another design pattern in and of themselves, helping users to get emotionally attached to and engage with the interface.
Another benefit of using animations is that they can create a perception that a site or app loads faster than it actually does.
A couple of house rules with animations
Have you ever bumped into a site that animates all the things? Wow, those can be jarring. So, here’s a couple of things to avoid when working with animations so our app doesn’t fall into the same boat:
Avoid animating CSS properties other than transform and opacity. If other properties have to be animated, like width or height, then make sure there aren’t a lot of layout changes happening at the same time. There’s actually a cost to animations and you can see exactly how much by referring to CSS Triggers.
Also, just because animations can create perceived performance gains, there’s actually a point of diminishing return when it comes to using them. Animating too many elements at the same time may result in decreased performance.
Now we can get our hands dirty with some code!
Let’s build a music app
We’re going to build the music app we looked at earlier, which is inspired by Aurélien Salomon’s Dribbble shot. I chose this example so that we can focus on animations, not only within a component, but also between different routes. We’ll build this app using Vue and create animations using vanilla (i.e. no framework) CSS.
Animations should go hand-in-hand with UI development. Creating UI before defining their movement is likely to cost much more time. In this case, the Dribbble shot provides that scope for us.
Let’s start with the development.
Step 1: Spin up the app locally
First things first. We need to set up a new Vue project. Again, we’re assuming some base-level understanding of Vue here, so please check out the Learning Vue guide for more info on setting up.
We need a couple of dependencies for our work, notably vue-router for transitioning between views and sass-loader so we can write in Sass and compile to CSS. Here’s a detailed tutorial on using routes and Sass can be installed by pointing the command line at the project directory and using npm install -D sass-loader node-sass.
We have what we need!
Step 2: Setting up routes
For creating routes, we’re first going to create two bare minimum components — Artists.vue and Tracks.vue. We’ll drop a new file in the src folder called router.js and add routes for these components as:
import Vue from 'vue'
import Router from 'vue-router'
import Artists from './components/Artists.vue'
import Tracks from './components/Tracks.vue' Vue.use(Router)
export default new Router({ mode: 'history', routes: [ { path: '/', name: 'artists', component: Artists }, { path: '/:id', name: 'tracks', component: Tracks } ]
})
Import router.js into the main.js and inject it to the Vue instance. Lastly, replace the content of your App.vue by <router-view/>.
Step 3: Create the components and content for the music app
We need two components that we’ll transition between with animation. Those are going to be:
Artists.vue: a grid of artists
Tracks.vue: An artist image with a back button
If you wanna jump ahead a bit, here are some assets to work with:
When all is said and done, the two views will come out to something like this:
Artists.vue (left) and Tracks.vue (right)
Step 4: Animate!
Here we are, the part we’ve really wanted to get to all this time. The most important animation in the app is transitioning from Artists to Tracks when clicking on an artist. It should feel seamless where clicking on an artist image puts that image in focus while transitioning from one view into the next. This is exactly the type of animation that we rarely see in apps but can drastically reduce cognitive load for users.
To make sure we’re all on the same page, we’re going to refer to the first image in the sequence as the “previous” image and the second one as the “current” image. Getting the effect down is relatively easy as long as we know the dimensions and position of the previous image in the transition. We can animate the current image by transforming it as per previous image.
The formula that I’m using is transform: translate(x, y) scale(n), where n is equal to the size of previous image divided by the size of current image. Note that we can use a static value of n since the dimensions are fixed for all the images. For example, the image size in the Artists view is 190x190 and 240x240 in the Tracks view. Thus, we can replace n by 190/240 = 0.791. That means the transform value becomes translate(x, y) scale(0.791) in our equation.
Animating from Artists to Tracks
Next thing is to find x and y. We can get these values though click event in the Artists view as:
…and then send these values to the Tracks view, all while switching the route. Since we aren’t using any state management library, the two components will communicate via their parent component, which is the top level component, App.vue. In App.vue, let’s create a method that switches the route and sends the image info as params.
Since we have received the position and ID of the image in Tracks, we have all the required data to show and animate it. We’ll first fetch artist information (specifically the name and image URL) using artist ID.
To animate the image, we need to calculate the transform value from the image’s starting position. To set the transform value, I’m using CSS custom properties, which can be done with CSS-in-JS techniques as well. Note that the image’s position that we received through props will be relative to window. Therefore we’ll have to subtract some fixed offset caused by the padding of the container <div> to even out our math.
We’ll use this value to create a keyframe animation to move the image:
@keyframes move-image { from { transform: var(--translate); }
}
This gets assigned to the CSS animation:
.image { animation: move-image 0.6s;
}
…and it will animate the image from this transform value to its original position on component load.
Transitioning from Artists to Tracks
We can use the same technique when going the opposite direction, Tracks to Artists. As we already have the clicked image’s position stored in the parent component, we can pass it to props for Artists as well.
Transitioning from Tracks to Artists
Step 5: Show the tracks!
It’s great that we can now move between our two views seamlessly, but the Tracks view is pretty sparse at the moment. So let’s add the track list for the selected artist.
We’ll create an empty white box and a new keyframe to slide it upwards on page load. Then we’ll add three subsections to it: Recent Tracks, Popular Tracks, and Playlist. Again, if you want to jump ahead, feel free to either reference or copy the final code from the repo.
The Tracks view with content
Recent Tracks is the row of thumbnails just below the artist image where each thumbnail includes the track name and track length below it. Since we’re covering animations here, we’ll create a scale-up animation, where the image starts invisible (opacity: 0) and a little smaller than it’s natural size (scale(0.7)), then is revealed (opacity: 1 )and scales up to its natural size (transform: none).
The Popular Tracks list and Playlist sit side-by-side below the Recent Tracks, where Popular tracks takes up most of the space. We can slide them up a bit on initial view with another set of keyframes:
To make the animation feel more natural, we’ll create a stagger effect by adding an incremental animation delay to each item.
@for $i from 1 to 5 { &:nth-child(#{$i + 1}) { animation-delay: #{$i * 0.05}s; }
}
The code above is basically looking for each child element, then adding a 0.05 second delay to each element it finds. So, for example, the first child gets a 0.05 second delay, the second child gets a 0.10 second delay and so on.
Check out how nice and natural this all looks:
Bonus: micro-interactions!
One of the fun things about working with animations is thinking through the small details because they’re what tie things together and add delight to the user experience. We call these micro-interactions and they serve a good purpose by providing visual feedback when an action is performed.
Depending on the complexity of the animations, we might need a library like anime.js or GSAP. This example is pretty straightforward, so we can accomplish everything we need by writing some CSS.
First micro-interaction: The volume icon
Let’s first get a volume icon in SVG format (Noun Project and Material Design are good sources). On click, we’ll animate-in and out its path element to show the level of volume. For this, we’ll create a method which switches its CSS class according to the volume level.
Do you like it when you click on Twitter’s heart button? That’s because it feels unique and special by the way it animates on click. We’ll make something similar but real quick. For this, we first get an SVG heart icon and add it to the the markup. Then we’ll add a bouncy animation to it that’s triggered on click.
Another fun thing we can do is add other small heart icons around it with random sizes and positions. Ideally, we’d add a few absolute-positioned HTML elements that a heart as the background. Let’s Arrange each of them as below by setting their left and bottom values.
We’ll also include a fade away effect so the icons appear to dissolve as they move upward by adding a keyframe animation on the same click event.
That’s all! I hope you find all this motivating to try animations on your own websites and projects.
While writing this, I also wanted to expand on the fundamental animation principles we glossed over earlier because I believe that they help choose animation durations, and avoid non-meaningful animations. That’s important to discuss because doing animations correctly is better than doing them at all. But this sounds like a whole another topic to be covered in a future article.
I was recently a guest editor for an issue of Bizarro Devs. It’s a great newsletter! Go sign up! I put in a bunch of links around blobs. Like those weird squishy random shapes that are so “in” right now. Here are those links as well. I’m always a fan of publishing stuff I write 😉
Blobs! Blobs are in! Blobs are — ahem — a bit bizarre. I’ll bask in a design like this annual report cover by Matt Pamer all day. I enjoy watching a design trend like this manifest itself in design tooling and become applied in lots of creative and crafty different ways.
We could start with <svg> and draw our own blob using the Pen tool that is pretty much stock in every vector design application. I’m a cheater though, and would probably wind up checking The Noun Project for some blob examples and steal the SVG from there. But sadly, there isn’t much there, at least as far as blobs go.
Once we have a blob, it’s just begging to be moved around. Monica Dinculescu shows how to do just that with pure CSS and liberal use of various CSS transforms in a keyframe animation:
A library like Greensock could help moving and morphing the blobs around. Greensock even has a plugin that is probably the most powerful morphing tool out there. This Pen uses Greensock, but adds some native SVG filters so that the blobs squish into each other satisfyingly. We could call it the gooey effect:
And blobs don’t have to be alone! Blobs that are squished together are like fluid. You might get a kick out of Peeke Kuepers article Simulating blobs of fluid.
Here’s the situation: You’ve bashed out a complicated design over two weeks of near full-time effort, gotten everything down to the exact spec of the design file, turn it in for stakeholder review and… you’re way off scope. Turns out a few folks on the team put their heads together, made some changes, and never sent you an updated comp.
Boo!
The unfortunate truth is that this happens all too often in front-end development, but it’s really no one person’s fault because it boils down to simple collective miscommunication and a lack of transparency on the team.
Well, that’s where a project management platform like monday.com comes into play. Even if you’re on a remote team or sitting in an office with cubicle walls up to the ceiling, monday.com bridges gaps and tears down walls that could throw a project off-track. With powerful and intuitive tools, like instant messaging for those ad hoc meetings, file storage for a centralized repository of assets, and an activity dashboard for catching up on the status of a project at a glance, monday.com brings project out into the light so everyone is in the loop and on the same page.
As you may know, the recent updates and additions to CSS are extremely powerful. From Flexbox to Grid, and — what we’re concerned about here — Custom Properties (aka CSS variables), all of which make robust and dynamic layouts and interfaces easier than ever while opening up many other possibilities we used to only dream of.
The other day, I was thinking that there must be a way to use Custom Properties to color an element’s background while maintaining a contrast with the foreground color that is high enough (using either white or black) to pass WCAG AA accessibility standards.
It’s astonishingly efficient to do this in JavaScript with a few lines of code:
var rgb = [255, 0, 0]; function setForegroundColor() { var sum = Math.round(((parseInt(rgb[0]) * 299) + (parseInt(rgb[1]) * 587) + (parseInt(rgb[2]) * 114)) / 1000); return (sum > 128) ? 'black' : 'white';
}
This takes the red, green and blue (RGB) values of an element’s background color, multiplies them by some special numbers (299, 587, and 144, respectively), adds them together, then divides the total by 1,000. When that sum is greater than 128, it will return black; otherwise, we’ll get white. Not too bad.
The only problem is, when it comes to recreating this in CSS, we don’t have access to a native if statement to evaluate the sum. So,how can we replicate this in CSS without one?
Luckily, like HTML, CSS can be very forgiving. If we pass a value greater than 255 into the RGB function, it will get capped at 255. Same goes for numbers lower than 0. Even negative integers will get capped at 0. So, instead of testing whether our sum is greater or less than 128, we subtract 128 from our sum, giving us either a positive or negative integer. Then, if we multiply it by a large negative value (e.g. -1,000), we end up with either very large positive or negative values that we can then pass into the RGB function. Like I said earlier, this will get capped to the browser’s desired values.
If my math is correct (and it’s very possible that it’s not) we get a total of 16,758, which is much greater than 255. Pass this total into the rgb() function for all three values, and the browser will set the text color to white.
At this point, everything seems to be working in both Chrome and Firefox, but Safari is a little cranky and gives a different result. At first, I thought this might be because Safari was not capping the large values I was providing in the function, but after some testing, I found that Safari didn’t like the division in my calculation for some reason.
Taking a closer look at the calc() function, I noticed that I could remove the division of 1,000 by increasing the value of 128 to 128,000. Here’s how that looks so far:
Throw in a few range sliders to adjust the color values, and there you have it: a dynamic UI element that can swap text color based on its background-color while maintaining a passing grade with WCAG AA.
Below is a Pen showing how this technique can be used to theme a user interface. I have duplicated and moved the --accessible-color variable into the specific CSS rules that require it, and to help ensure backgrounds remain accessible based on their foregrounds, I have multiplied the --accessible-color variable by -1 in several places. The colors can be changed by using the controls located at the bottom-right. Click the cog/gear icon to access them.
A little while back, Facundo Corradini explained how to do something very similar in this post. He uses a slightly different calculation in combination with the hsl function. He also goes into detail about some of the issues he was having while coming up with the concept:
Some hues get really problematic (particularly yellows and cyans), as they are displayed way brighter than others (e.g. reds and blues) despite having the same lightness value. In consequence, some colors are treated as dark and given white text despite being extremely bright.
What in the name of CSS is going on?
He goes on to mention that Edge wasn’t capping his large numbers, and during my testing, I noticed that sometimes it was working and other times it was not. If anyone can pinpoint why this might be, feel free to share in the comments.
Further, Ana Tudor explains how using filter + mix-blend-mode can help contrast text against more complex backgrounds. And, when I say complex, I mean complex. She even goes so far as to demonstrate how text color can change as pieces of the background color change — pretty awesome!
So, count this as yet another approach to throw into the mix. It’s incredibly awesome that Custom Properties open up these sorts of possibilities for us while allowing us to solve the same problem in a variety of ways.
There have been some interesting, boundary-pushing typography-related experiments lately. I was trying to think of a joke like “somethings in the descenders” but I just can’t find something that will stand on its own leg without being easy to counter.
Note the special <div> at the top with the full word in it, while those empty <b> elements do the actual drawing of the glyphs. I wouldn’t call it entirely accessible, as I’d argue part of accessibility is stuff like find-on-page with highlighting and selectable text. But this is obviously an artistic experiment and your implementation could go any number of ways. I’d love to see an attempt at setting transparent SVG <text> over the top of it that is sized the same so that the text is selectable.
Harbor Type recently put out Rocher Color, a free color font. Yes, color font. That’s a thing. And Rocher Color is actually a color font and a variable font.
Support seems kinda decent to me, but it’s complicated because there are a bunch of different kinds all with different support across browsers.
The other story is that they are, well, kinda humongous, size-wise. The woff2 file is probably the most relevant here as it’s such a modern feature anyway. The download from the site (RocherColorGX.woff2) clocks in at 178KB. Not something you’d just toss on a page for a single headline probably, considering it’s not just weight with fonts — but you’re also always fighting the FOUT/FOIT battle.
I think to justify using a beefy color font like this you’d…
Use it quite a bit around the site for dynamic headlines
Customize the colors to be perfect for you (ahead of time)
Make use of the fancy variable font features like the bevel and shadow adjustments (on the fly)
If you don’t see yourself doing those things, you might be better off using <svg> with these shapes all expanded out to paths. You could still use this font to make the SVG, assuming your design tool supports this kind of font. You won’t get text wrapping or anything, but the file size and loading speed will be much faster. Or you could even use a graphic format like PNG/WebP, and there’s no terrible shame in that if you still use a semantic element for the headline (visually hidden, of course). You won’t get find-on-page highlighting or select-ability, but might be an OK trade-off for a one-off.
Kenneth Ormandy has rounded up some more interesting typographic experiments in CSS. In his post, he mentions Diana Smith’s Pure CSS Font, which builds itself from empty elements and all kinds of fancy CSS trickery to draw the shapes.
The point of this project is right in the header:
For private, SEO-hidden, CAPTCHA-friendly unselectable text. Deter plagiarism and spambots!
Hidden for assistive technology too, so careful there, but it seems to me this project is more about exploring possibilities. After all, it’s the letters that power Diana’s remarkable CSS paintings like Zigaro.
Don’t miss Kenneth’s post, as he links to lots more fascinating examples of people being typographers with very unconventional tools. Kenneth takes a crack himself with this fascinating little experiment, using a button there to expose the tricks within:
"Why do I need a 4Ghz quadcore to run facebook?" This is why. A single word split up into 11 HTML DOM elements to avoid adblockers. pic.twitter.com/Zv4RfInrL0
I popped over to Facebook to verify that and what I saw was a different and even more nested mess:
They are trying to fight your ad blocker browser extension. Of course they are. I’m sure at their scale not doing this means losing millions of dollars. But I wonder if it’s really losing money when you factor in losing trust, and potentially losing people on the platform entirely.
It just feels so rude, doesn’t it? Like a user specifically installs technology onto their computer in order to exert some control over what they allow onto their computers and into their eyeballs. And they are saying, “No, we do not respect that choice. We are going to fight your technology with our technology and force feed this stuff onto your computer and your eyeballs.” Doesn’t sit right.
I’m not unaware that ad blockers have ad adverse effect on the ability for websites to make money. That’s quite literally how I make money. But I don’t want to do it fighting and at the expense of breaking trust. I want to do it gracefully while building trust.
Anyway.
I wonder what writing HTML to help ad blockers would look like instead:
This span-based lettering stuff makes me think of libraries like Splitting.js and Lettering.js that break up text into individual <span>s for styling reasons.
Turns out that doesn’t affect on-page search (i.e. if you search for “dog,” you’ll find <span>d</span><span>o</span><span>g</span>), but it does affect some screen readers in that they will treat each letter distinctly, which can result in pretty awful audio output, like pauses between letters where you wouldn’t expect or want them.
Have you seen Diana Smith’s CSS drawings? Stunning. These far transcend the CSS drawings that sort of crudely replicate a flat SVG scene, like I might attempt. We were lucky enough for her to post some of her CSS drawing techniques here last year.
Well, Diana has also listed the top five CSS properties she uses to get these masterpieces done, and they are surprising in their plainness:
border-radius
box-shadow
transform
gradients
overflow
…but of course, layered in trickery!
… for custom rounded elements that are meant to mimic organic objects like faces, it is imperative that you become intimately familiar with all eight available parameters in the border-radius property.
Diana shows her famous Francine drawing with each of the most used properties turned off:
Without border-radiusWithout transform
Be sure to check out this VICE interview she did as well. She covers gems like the fact that Francine was inspired by American Dad (lol) and that the cross-browser fallbacks are both a fascinating and interesting mess.
I love the idea of programmatically generated images. That power is close at hand these days for us front-end developers, thanks to the concept of headless browsers. Take Puppeteer, the library for controlling headless Chrome. Generating images from URLs is their default use case:
That ought to get the ol’ mind grape going. What if we had URLs on our site that — with the power of our HTML and CSS skills — created perfect little designs for sharing using dynamic data… then turned them into images and used them for our meta tags?
Since the design part is entirely an HTML/CSS adventure, I’m sure you could imagine a setup where the URL passed in parameters that did things like set copy and typography, colors, sizes, etc. Zeit built exactly that!
Kind of amazing that you can spin up an entire browser in a cloud function! Netlify also offers cloud functions, and when I mentioned this to Phil Hawksworth, he told me he was already doing this for his blog!
So on a blog post like this one, an image like this is automatically generated:
Brad points out some UX problems with a variety of apps that are doing things a little outside of the norm when it comes to their login forms. There is already a bunch of things to get right with forms to begin with (e.g. use the right input types, label your inputs, don’t have whack password requirements, use SSL, etc.)… OMG why complicate it even more?!
A “password manager test” should be a development best practice here. Does it work cleanly with the built-in browser password manager? How about 1Password and LastPass? No? Give it some love, please and thank you.