Front End Web Development

What We Want from Grid

Css Tricks - Tue, 02/26/2019 - 3:14pm

We felt spoiled with CSS grid for a minute there. It arrived hot and fast in all the major browsers all at once. Now that we're seeing a lot more usage, we're seeing people want more from grid.

Michelle Barker lists hers wants (and I'll put my commentary after):

  • Styling row and column gaps. I've also heard requested styling grid cells directly, rather than needing to place an element there and style that element.
  • Multiple gap values. I wanted this just the other week, and I was told to use an empty column or row instead of a gap. The size of that column can be controlled, and things are placed accordingly to treat it like a gap. Sort of OK, except that isn't particularly friendly to implicit grids.
  • Autoflow patterns. This is clever. Check out Michelle's use case and proposal.
  • calc() with the fr unit. This is a mindbender. I can see wanting to do something like calc(1fr - 100px), but then isn't the leftover space 100px short and 1fr recalcuated to fill that space? Seems infinite loopy.
  • Aspect ratio grid cells. I suspect, if we get this, it'll be a generic aspect ratio solution that will work on any element, including elements placed onto a grid.

Subgrid is also starting to be hotly requested, and I can see why. While building the last page layout I did using grid, I found myself strongly wishing I could share the overall page grid lines within sub-elements.

Rachel Andrew talked about its status about six months ago in CSS Grid Level 2: Here Comes Subgrid. I'm not sure where it's at now, but I don't think any browser is supporting it quite yet. (I'm not even sure if the spec is technically done.)

Brad put a point on the desire here:

Container queries and subgrid would make my design system work so much easier.

Define a grid and throw some components in there, then watch them snap into place to the parent grid and look great no matter what the container dimensions are.

— Brad Frost (@brad_frost) February 11, 2019

And Ken Bellows writes:

  • If we combine subgrid with grid-template-areas within the cards (read my last post if you don't know about Grid Areas, it'll blow your mind), complex responsive card-based layouts become trivial.
  • The prospect of a subgrid on both axes gives us a way to sort of accomplish relative grid positioning, at least for semantically grouped items, like I wished I had above! Group your stuff in a container, position your container on the grid, make that container a subgrid on both axes, and declare your tracks relative to the subgrid element's grid position!
  • Between Flexbox, Grid, display: contents, and subgrids, we will finally have everything we need to write very slim, clean, semantic markup with basically no fluff or purely structural elements. It will be a huge boon for accessibility, SEO, and just developers trying to understand your markup!

Eric Meyer called subgrid an essential feature three years ago:

This is why I’ve come to the same conclusion other grid experts (like Rachel) already have: subgrids are a major component of grid layout, and should be a part of any grid layout implementation when it emerges from developer-preview status.  If that means delaying the emergence of grids, I think it’s worth it.

And of course, everybody still wants native masonry. ;)

The post What We Want from Grid appeared first on CSS-Tricks.

Look Ma, No Media Queries! Responsive Layouts Using CSS Grid

Css Tricks - Tue, 02/26/2019 - 3:14pm

Not only has CSS Grid reshaped the way we think and build layouts for the web, but it has also contributed to writing more resilient code, replacing "hacky" techniques we've used before, and in some cases, killing the need to rely on code for specific resolutions and viewports. What's so cool about this era in web development is that we're capable of doing more and more with fewer lines of code.

In this article, we'll start dipping our toes into the power of CSS Grid by building a couple of common responsive navigation layouts. It's easier than what you may think, and since CSS Grid was built with responsiveness in mind, it'll take less code than writing media queries all over the place. Let’s do this!

Layout #1: Hero content and list of articles

See the Pen
Hero Content and List of Articles
by Juan Martín García (@imjuangarcia)
on CodePen.

We'll kick off this set of examples by creating a common website layout: A full-width hero section, with a grid of cards below.

Both elements will respond to window resizing and adapt accordingly. Though this might seem like a lot of code at first glance, the responsive behavior is done with only six lines of CSS Grid code, and without writing a single @media rule. Let's break down the code to see what's going on:

The hero section

Let’s take a look at the code for the .hero element:

<section class="hero"> <h1>You thirsty?</h1> <article> <p>Explore local breweries with just one click and stirred by starlight across the centuries light years great turbulent clouds circumnavigated paroxysm of global death.</p> <a href="#breweries">Browse Breweries</a> </article> </section> .hero { /* Photo by mnm.all on Unsplash */ background: url('https://images.unsplash.com/photo-1518176258769-f227c798150e') center; background-size: cover; padding: 4rem 2rem; /* Grid styles */ display: grid; align-items: center; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }

We have a bunch of background styles to enable the beer background, a bit of padding to separate the content from the edge of the screen, and then three lines of grid styles:

  1. The first line (display: grid;) is changing the behavior of the .hero element to be a grid container. That means the elements inside .hero are now grid items.
  2. The second line (align-items: center;) is going to vertically center the columns on our grid. But these two lines don't do anything on their own until we set the columns of our grid.
  3. And that's where the third line comes in. A lot of stuff is going on in that single property, so let's go one step at a time.
The repeat() function

Generally speaking, what we usually do to define our columns and rows on a CSS Grid is to add the value for each track after defining the property, like this:

.element { /* This will result on four columns, each one of 1fr */ grid-template-columns: 1fr 1fr 1fr 1fr; /* This will result on two rows, each one of 300px */ grid-template-rows: 300px 300px; }

Now, that's quite dull. We can use the repeat() function to make that less verbose and easier to follow. The function takes two parameters:

  1. The number of times to repeat the value.
  2. The value itself.

After refactoring our code to use repeat(), we should expect the same results from these lines of code:

.element { /* this is the same as grid-template-columns: 1fr 1fr 1fr 1fr; */ grid-template-columns: repeat(4, 1fr); /* this is the same as grid-template-rows: 300px 300px; */ grid-template-rows: repeat(2, 300px); }

Much cleaner, yeah?

The minmax() function

Now, the above examples are explicitly defining sizes for the tracks (1fr and 300px). That might work for some scenarios, but for our beer example here, we need to be able to automatically calculate the size of the track, based on the width of the viewport, and automatically adjust the number of columns shown. To be able to do that, we'll define a range of values using the minmax() function. What will we be defining? You've probably guessed by now: The *minimum* and *maximum* values we want these columns to be able to resize to.

In the hero for our beer example above, we set our minmax() property to be 240px at its minimum size, and 1fr at its maximum size. fr units, if you've never heard of them, stand for fractional units. Nobody can explain them better than Jen Simmons on this video and Robin Rendle in this post.

Using the Firefox Grid Inspector to check the change on the track's size when resizing

That results in our tracks being 1fr when there's plenty of space on our viewport (aka desktop resolutions), and 240px when there's not enough space for both columns (like on mobile devices). That's why they nicely grow when we make our browser wider, since they're taking the remaining space and equally dividing it across the existing columns. Now, moving to the last piece of the puzzle!

The auto-fit keyword

The auto-fit keyword allows us to wrap our columns into rows when there's not enough space in our viewport to fit the 240px minimum value without overflowing the content. Sara Soueidan wrote an excellent article about auto-sizing columns using the auto-fill and auto-fit keywords, in case you want to dive a little deeper into what's going on under the hood. Now, with that last bit of code in place, we should be able to achieve this result:

The column is automatically wrapping when there's not enough space in the viewport The article list

Now that we've thoroughly reviewed the behavior of the elements inside our hero element, it's likely that the first two lines of CSS code for the breweries list below it might already seem familiar to you:

.breweries > ul { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); grid-gap: 1rem; }

That's right! We're using the exact same approach: On the first line we define our grid, on the second one we size our tracks using the same magic one-liner, and on the third line we set a gap for these columns. Nothing new under the sun, and what's really neat about this, is that our code is resilient enough to adjust the number of tracks and their sizes, according to the number of items we have inside our unordered list:

The grid responds to the change in the number of tracks, and adapts the layout

That's all, folks! A fully responsive website layout, using just six lines of CSS code. Not bad, huh? Make sure you check the source code and play around with this example on CodePen.

Layout #2: Full-width image gallery

See the Pen
Full Width Image Gallery
by Juan Martín García (@imjuangarcia)
on CodePen.

On this next example, we'll embrace the power of our newly learned combination of repeat(), auto-fit and minmax() to create this responsive image gallery. We'll also be sizing our tracks using grid-column and grid-row, and learning about the handy property:value combination of grid-auto-flow: dense; that allows us to change the default behavior of the elements that can't fit on our explicit tracks: Instead of wrapping themselves in new rows or columns, we'll make them fit into the unused spots on our grid. Let's get into the coding!

The grid setup

The grid is created using our familiar display: grid; property, where columns are defined using repeat(), auto-fit and minmax(). We also added a bunch rows with a repeat() function and defined a gap to our images, using grid-gap. But the new player here is the grid-auto-flow: dense;. We’ll get to it in a second.

.gallery > .gallery__list { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); grid-template-rows: repeat(6, 200px); grid-gap: 1rem; grid-auto-flow: dense; }

We also created a repetition pattern using the nth-child() pseudo-selector to set different sizes for our tracks using grid-column and grid-row. Notice here that we’re using the span keyword to allow the selected item to occupy more than one column or row.

/* This will create 2x images every 4 elements */ .gallery > .gallery__list > li:nth-child(4n) { grid-column: span 2; /* Spans two columns */ grid-row: span 2; /* Spans two rows */ } /* This will create 3x images every 8 elements */ .gallery > .gallery__list > li:nth-child(8n) { grid-column: span 3; grid-row: span 3; }

And finally, we'll make sure our images cover the entire area of its container, regardless if it's 1x, 2x or 3x, using object-fit: cover;. If you have never heard of object-fit, it works fairly similar to how background-image does, but with HTML <img> tags:

.gallery > .gallery__list > li > figure > img { width: 100%; height: 100%; object-fit: cover; }

Now, the real deal here is grid-auto-flow: dense;. Check what happens when we take that out from our code:

Removing grid-auto-flow: dense; leads to inconsistent placement of the elements on the grid

See those holes on our beautifully crafted grid? That's because some of the elements on it are taking 2x or 3x spots, and when there isn't enough space on our tracks to fit them, they'll wrap into a new row, since that's the default behavior. By changing it from row to dense, we're telling the grid to fill any gaps we might have with elements that could fit them, regardless of their source order on the DOM.

That's why this technique might come especially handy for things like image galleries, but might not be suitable for other use cases where you might need to preserve the order of the markup. Feel free to play around with the CodePen demo to check the differences between where items are placed.

Layout #3: Trello-style card layout

See the Pen
Trello-Style Card Layout
by Juan Martín García (@imjuangarcia)
on CodePen.

Now, on to the last demo, where we'll take advantage of the ability to nest grids to recreate this Trello Board. We'll be creating a grid to hold our four different columns, and inside of those, we'll create a child grid for our cards. Even though this example won't explore new properties or revolutionary methods, it'll help us to get a grasp on how easy it is to build complex layouts with a few lines of CSS code. This demo has a lot of extra code to achieve the styling of the Trello layout, so we’ll focus solely on the grid styles.

The columns

To create the four columns, we'll use display: grid; on the container and use our magical one-liner for our grid-template-columns. We'll also be defining a gap between them, and use align-items: flex-start; to ensure that our columns don't stretch to the bottom of the screen.

.column__list { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); grid-gap: .5rem; align-items: flex-start; }

Now, the original Trello is not responsive by default: If you resize your browser on a Trello Board, you'll notice that you'll end up having a horizontal scroll on your columns, rather than wrapping them on a new row. We're not following that behavior here since we want to build responsive layouts, but in case you're curious, and want to emulate Trello's functionality, you can achieve that by adding two more lines of CSS code:

.column__list { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); grid-gap: .5rem; align-items: flex-start; /* Uncomment these lines if you want to have the standard Trello behavior instead of the column wrapping */ grid-auto-flow: column; grid-auto-columns: minmax(260px, 1fr); }

We learned about grid-auto-flow in our previous demo and discovered that it let us control how the auto-placement algorithm work, and how implicit elements should be added in the flow of the grid. The default behavior is row, meaning that any extra element that won't fit on our grid will wrap into a new line. We changed that to be dense on our previous demo, and we'll change it to be column on this one: That way, any new column added here will end up in an implicit column, and have a horizontal scroll. We'll also define a width for those auto-generated columns with the grid-auto-columns property.

Modifying the grid-auto-flow property will make this demo behave like the real-world Trello The cards

For the cards grid, we'll use a similar approach. We'll display: grid; on the container. We won't define any columns here, since we don't want to have any, and we'll put grid-template-rows: auto; to use to avoid all cards having the same height — we want some of them to be bigger and some of them smaller, based on the type of content being added to them.

.card__list { display: grid; grid-template-rows: auto; grid-gap: .5rem; margin: .5rem 0; }

And, again, that's all folks! Two more lines to set a gap and a margin to the cards, and we're done! Everything else in the Pen is standard CSS to achieve the Trello look and feel.

So then... are media queries dead?

Back in the day, when we were building layouts using display: inline-block or floats, media queries made a lot of sense in order to change the size of our elements as the viewport got smaller. But now, with the incredibly powerful layouts that we're able to create with a couple of CSS lines, you might feel tempted to think that media queries are doomed. I strongly disagree with that: I believe that we should change the way we think about them, and therefore use them differently.

As Rachel Andrew stated about a year ago, we should use media queries to fix our layout when it breaks, rather than targeting devices: There are so many out there! With the advent of Media Queries Level 4 and 5, we're not only able to detect screen sizes now, but pointer types as well. As a result, we can dig into a user’s system preferences and adapt our code for those who prefer reduced motion or whether we should use inverted colors. That means media queries are not dead; on the flipside, I'd say it's an exciting time for using media queries, but we need to learn to use them right. In the meantime, building robust layouts using modern techniques such as Flexbox or CSS Grid, will save you a bunch of time, code, and headaches.

The post Look Ma, No Media Queries! Responsive Layouts Using CSS Grid appeared first on CSS-Tricks.

The CSS mental model

QuirksBlog - Tue, 02/26/2019 - 5:35am

I am likely going to write a “CSS for JavaScripters” book, and therefore I need to figure out how to explain CSS to JavaScripters. This series of article snippets are a sort of try-out — pre-drafts I’d like to get feedback on in order to figure out if I’m on the right track.

Today we will attempt to describe the different mental models for CSS and JavaScript. Everybody agrees there is a difference, but nobody’s able to define exactly what that difference is. So let’s try.

(Also, at the last moment I switched from describing CSS as “context-based” to “state-based.” I hope that makes more sense, and it’s one of the points I’d like feedback on.)

CSS and JavaScript mental models

Programming CSS requires a different mental model than programming JavaScript. CSS is a declarative language, while JavaScript is an imperative language. (Also, it’s an open question whether CSS is a programming language at all. We’ll get back to that later, but for now we’ll pretend it is.)

Those who have experience with declarative languages such as Prolog, or even spreadsheets, will have the advantage over people who only know imperative languages, who may be confused by CSS at first, since it lacks many of the control structures they’re used to in JavaScript.

The differences go deeper, though. Fundamentally, JavaScript execution is time-based. That is, everything happens in the order prescribed by the program. There is a time, at the very start of execution, that a certain variable does not exist yet. Then it’s defined and assigned a value, and later that value is changed, and so on. An if-statement based on that variable will have different outcomes at different times.

Not so CSS. All CSS declarations get their value at the same time, and they all take effect at the same time. It is impossible for any CSS declaration to be applied earlier than any other CSS declaration. Declaration order matters, but any conflict is resolved immediately and doesn’t require (or even allow) control structures. The same CSS will always give the same result.

State-driven change

[Could I even say “state-based programming?”]

CSS does accept changes to the initial rendering of the page, but it is fundamentally state-driven. It can only react to a limited number of well-defined state changes in a web page. A good example is changing a background color on hover. nav a:hover { background-color: red; }

When the link’s state changes (i.e. the mouse pointer hovers over it), CSS switches from one set of instructions to the other, and when the state changes back to no-hover, CSS switches back to the original instruction set.

You can achieve the same effect with a few lines of JavaScript, but it’s instructive to study the differences. el.onmouseover = function () { this.style.backgroundColor = 'red' } el.onmouseout = function () { this.style.backgroundColor = ''; }

First, something that’s so obvious that it’s hardly ever mentioned: JavaScript needs CSS in order to actually change the background color. It is impossible to do this in any other way. Conversely, the CSS declaration does not need JavaScript. When it comes to styling, CSS is more fundamental than JavaScript - closer to how browsers actually work, and thus much faster.

Next, JavaScript needs two statements instead of CSS’s one. It does not detect a state change automatically, as CSS does. Instead, you have to take it by the hand and guide it through all possible options, and make sure it notices not only the state change, but also the change back.

Then, JavaScript needs an extra control structure to make sure that the state change is detected on all links in the navigation instead of just one. This is not particularly difficult, but it needs to be done. Again, with its single selector CSS is more elegant.

Still, JavaScript has its advantages as well. Unlike CSS, JavaScript allows you to cancel the background change by adding an if-statement to determine whether the link background change should take place. In CSS you defined the styles to be applied in a state of hover, and those instructions are always followed. If you want more fine-grained control, JavaScript is the better solution.

Elegance vs control

More fine-grained control is not an end in itself. It all depends on the context. Sometimes, like in the background example, the simple, elegant, fast solution is better. In more advanced situations there comes a time when JavaScript, with its fine-grained control, becomes the better answer.

Keith Grant pointed out an interesting analogy. If we as humans wish to run, we just tell our body to run, and it obeys. We could deconstruct the act of running into its constituent parts like “raise left knee,” “raise left foot,” “advance left leg,” and so on, but that is much harder to do and we’d likely fall over, as this game shows.

In this analogy, the run command would be CSS, and the detailed foot-and-leg instructions would be JavaScript. The analogy is flawed, as all are, since as humans we’ll almost never operate in a context that requires us to deconstruct the act of running, while a web page might benefit from deconstructing the act of changing background colors. Still, the analogy might help you to understand the advantages of the CSS mental model better.

It doesn’t answer the most important question, though. When do we cross the line? When does JavaScript become the better option? In the end, that depends on your context, both the project you’re working on and your familiarity with CSS and JavaScript. Still, I have the feeling that JavaScripters who are unfamiliar with CSS tend to draw the line too early, and that their simpler use cases might be better served by a pure CSS solution. The choice is yours

So the choice is yours. Elegant, but limited, state-driven simplicity versus controlled, but complicated, time-based execution. There is no right or wrong here — just a careful weighting of options and contexts.

Whatever you choose for a particular project, if you work with browsers you should have a basic understanding of both approaches. And if you want to master CSS you need to understand state-based programming and the mental model that goes with it.

Feedback

Badly formatted

https://twitter.com/ptrdo/status/1100425471802585088
This is a very good approach. Perhaps another aspect of declarative v imperative (assumed but not mentioned) is how declarative rule-setting defines characteristics which can be universal and prescribed without the elements needing to exist, while imperative expects an instance.

https://twitter.com/tabatkins/status/1100421543144841216
The bit about "needing an extra control structure" could use some slight expansion. You need a loop over all links inside of nav (itself probably obtained with a selector), then a mutation observer to *add* the listeners for new links and *remove* them if the link is moved.

State machines: https://medium.com/@DavidKPiano/css-animations-with-finite-state-machines-7d596bb2914a

https://adactio.com/links/14866
I’m not sure if I agree with describing CSS as being state-based. The example that illustrates this—a :hover style—feels like an exception rather than a typical example of CSS.

https://twitter.com/leifastrand/status/1100801652586659843
Declarative = you describe the intended outcome. Imperative = you describe the steps to take. JS devs often encounter something similar: use map, filter and reduce over a collection to define intended result, or imperatively define the steps to take as a for loop.

Mail
JS is verbs, CSS is nouns.

Responsive Designs and CSS Custom Properties: Building a Flexible Grid System

Css Tricks - Tue, 02/26/2019 - 5:28am

Last time, we looked at a few possible approaches for declaring and using CSS custom properties in responsive designs. In this article, we’ll take a closer look at CSS variables and how to use them in reusable components and modules. We will learn how to make our variables optional and set fallback values.

As an example, we will build a simple grid system based on flexbox. Grid systems play a vital role in responsive designs. However, building a grid system that is flexible and lightweight at the same time can be a tricky task. Let’s see what the common approaches towards grid systems are and how CSS custom properties can help us build them.

Article Series:
  1. Defining Variables and Breakpoints
  2. Building a Flexible Grid System (This Post)
A simple CSS grid system

Let’s start with a 12-column grid system:

.container { max-width: 960px; margin: 0 auto; display: flex; } .col-1 { flex-basis: 8.333%; } .col-2 { flex-basis: 16.666%; } .col-3 { flex-basis: 25%; } .col-4 { flex-basis: 33.333%; } .col-5 { flex-basis: 41.666%; } .col-6 { flex-basis: 50%; } /* and so on up to 12... */

See the Pen
#5 Building responsive features with CSS custom properties
by Miko?aj (@mikolajdobrucki)
on CodePen.

There’s quite a lot of repetition and hard-coded values here. Not to mention how many more will be generated once we add more breakpoints, offset classes, etc.

Building a grid system with Sass

To make our grid example more readable and maintainable, let’s use Sass to preprocess our CSS:

$columns: 12; // Number of columns in the grid system .container { display: flex; flex-wrap: wrap; margin: 0 auto; max-width: 960px; } @for $width from 1 through $columns { .col-#{$width} { flex-basis: $width / $columns * 100%; } }

See the Pen
#6 Building responsive features with CSS custom properties
by Miko?aj (@mikolajdobrucki)
on CodePen.

This is definitely much easier to work with. As we develop our grid further and, let’s say, would like to change it from 12 columns to 16 columns, all we have to do is to update a single variable (in comparison to dozens of classes and values). But... as long as our Sass is shorter and more maintainable now, the compiled code is identical to the first example. We are still going to end up with a massive amount of code in the final CSS file. Let’s explore what happens if we try to replace the Sass variables with CSS custom properties instead.

Building a grid system with CSS custom properties

Before we start playing with CSS custom properties, let’s start with some HTML first. Here’s the layout we’re aiming for:

It consists of three elements: a header, a content section and a sidebar. Let’s create markup for this view, giving each of the elements a unique semantic class (header, content, sidebar) and a column class which indicates that this element is a part of a grid system:

<div class="container"> <header class="header column"> header </header> <main class="content column"> content </main> <aside class="sidebar column"> sidebar </aside> </div>

Our grid system, as before, is based on a 12-column layout. You can envision it as an overlay covering our content areas:

So .header takes all 12 columns, .content takes eight columns (66.(6)% of the total width) and .sidebar takes four columns (33.(3)% of the total width). In our CSS, we would like to be able to control the width of each section by changing a single custom property:

.header { --width: 12; } .content { --width: 8; } .sidebar { --width: 4; }

To make it work, all we need to do is write a rule for the .column class. Lucky for us, most of the work is already done! We can re-use the Sass from the previous chapter and replace the Sass variables with CSS custom properties:

.container { display: flex; flex-wrap: wrap; margin: 0 auto; max-width: 960px; } .column { --columns: 12; /* Number of columns in the grid system */ --width: 0; /* Default width of the element */ flex-basis: calc(var(--width) / var(--columns) * 100%); }

Notice two important changes here:

  1. The --columns variable is now declared inside of the .column rule. The reason is that this variable is not supposed to be used outside of the scope of this class.
  2. The math equation we perform in the flex-basis property is now enclosed within a calc() function. Math calculations that are written in Sass are compiled by the preprocessor and don’t need additional syntax. calc(), on the other hand, lets us perform math calculations in live CSS. The equation always needs to be wrapped within a calc() function.

On a very basic level, that’s it! We’ve just built a 12-column grid system with CSS custom properties. Congratulations! We could call it a day and happily finish this article right now, but... we usually need a grid system that is a bit more sophisticated. And this is when things are getting really interesting.

See the Pen
#8 Building responsive features with CSS custom properties
by Miko?aj (@mikolajdobrucki)
on CodePen.

Adding a breakpoint to the grid

Most times, we need layouts to look different on various screen sizes. Let’s say that in our case we want the layout to remain as it is on a large viewport (e.g. desktop) but have all three elements become full-width on smaller screens (e.g. mobile).

So, in this case, we would like our variables to look as follows:

.header { --width-mobile: 12; } .content { --width-mobile: 12; --width-tablet: 8; /* Tablet and larger */ } .sidebar { --width-mobile: 12; --width-tablet: 4; /* Tablet and larger */ }

.content and .sidebar each hold two variables now. The first variable (--width-mobile) is a number of columns an element should take by default, and the second one (--width-tablet) is the number of columns an element should take on larger screens. The .header element doesn’t change; it always takes the full width. On larger screens, the header should simply inherit the width it has on mobile.

Now, let’s update our .column class.

CSS variables and fallback

To make the mobile version work as expected, we need to alter the .column class as follows:

.column { --columns: 12; /* Number of columns in the grid system */ --width: var(--width-mobile, 0); /* Default width of the element */ flex-basis: calc(var(--width) / var(--columns) * 100%); }

Basically, we replace the value of the --width variable with --width-mobile. Notice that the var() function takes two arguments now. The first of them is a default value. It says: "If a --width-mobile variable exists in a given scope, assign its value to the --width variable." The second argument is a fallback. In other words: "If a --width-mobile variable is not declared in a given scope, assign this fallback value to the --width variable." We set this fallback to prepare for a scenario where some grid elements won’t have a specified width.

For example, our .header element has a declared --width-mobile variable which means the --width variable will be equal to it and the flex-basis property of this element will compute to 100%:

.header { --width-mobile: 12; } .column { --columns: 12; --width: var(--width-mobile, 0); /* 12, takes the value of --width-mobile */ flex-basis: calc(var(--width) / var(--columns) * 100%); /* 12 ÷ 12 × 100% = 100% */ }

If we remove the --width-mobile variable from the .header rule, then the --width variable will use a fallback value:

.header { /* Nothing here... */ } .column { --columns: 12; --width: var(--width-mobile, 0); /* 0, takes the the fallback value */ flex-basis: calc(var(--width) / var(--columns) * 100%); /* 0 ÷ 12 × 100% = 0% */ }

Now, as we understand how to set fallback for CSS custom properties, we can create a breakpoint, by adding a media query to our code:

.column { --columns: 12; /* Number of columns in the grid system */ --width: var(--width-mobile, 0); /* Default width of the element */ flex-basis: calc(var(--width) / var(--columns) * 100%); } @media (min-width: 576px) { .column { --width: var(--width-tablet); /* Width of the element on tablet and up */ } }

This works exactly as expected, but only for the content and sidebar, i.e. for the elements that have specified both --width-mobile and --width-tablet. Why?

The media query we created applies to all .column elements, even those that don’t have a --width-tablet variable declared in their scope. What happens if we use a variable that is not declared? The reference to the undeclared variable in a var() function is then considered invalid at computed-value time, i.e. invalid at the time a user agent is trying to compute it in the context of a given declaration.

Ideally, in such a case, we would like the --width: var(--width-tablet); declaration to be ignored and the previous declaration of --width: var(--width-mobile, 0); to be used instead. But this is not how custom properties work! In fact, the invalid --width-tablet variable will still be used in the flex-basis declaration. A property that contains an invalid var() function always computes to its initial value. So, as flex-basis: calc(var(--width) / var(--columns) * 100%); contains an invalid var() function the whole property will compute to auto (the initial value for flex-basis).

What else we can do then? Set a fallback! As we learned before, a var() function containing a reference to the undeclared variable, computes to its fallback value, as long as it’s specified. So, in this case, we can just set a fallback to the --width-tablet variable:

.column { --columns: 12; /* Number of columns in the grid system */ --width: var(--width-mobile, 0); /* Default width of the element */ flex-basis: calc(var(--width) / var(--columns) * 100%); } @media (min-width: 576px) { .column { --width: var(--width-tablet, var(--width-mobile, 0)); } }

See the Pen
#9 Building responsive features with CSS custom properties
by Miko?aj (@mikolajdobrucki)
on CodePen.

This will create a chain of fallback values, making the --width property use --width-tablet when available, then --width-mobile if --width-tablet is not declared, and eventually, 0 if neither of the variables is declared. This approach allows us to perform numerous combinations:

.section-1 { /* Flexible on all resolutions */ } .section-2 { /* Full-width on mobile, half of the container's width on tablet and up */ --width-mobile: 12; --width-tablet: 6; } .section-3 { /* Full-width on all resolutions */ --width-mobile: 12; } .section-4 { /* Flexible on mobile, 25% of the container's width on tablet and up */ --width-tablet: 3; }

One more thing we can do here is convert the default 0 value to yet another variable so we avoid repetition. It makes the code a bit longer but easier to update:

.column { --columns: 12; /* Number of columns in the grid system */ --width-default: 0; /* Default width, makes it flexible */ --width: var(--width-mobile, var(--width-default)); /* Width of the element */ flex-basis: calc(var(--width) / var(--columns) * 100%); } @media (min-width: 576px) { .column { --width: var(--width-tablet, var(--width-mobile, var(--width-default))); } }

See the Pen
#10 Building responsive features with CSS custom properties
by Miko?aj (@mikolajdobrucki)
on CodePen.

Now, we have a fully functional, flexible grid! How about adding some more breakpoints?

Adding more breakpoints

Our grid is already quite powerful but we often need more than one breakpoint. Fortunately, adding more breakpoints to our code couldn’t be easier. All we have to do is to re-use the code we already have and add one variable more:

.column { --columns: 12; /* Number of columns in the grid system */ --width-default: 0; /* Default width, makes it flexible */ --width: var(--width-mobile, var(--width-default)); /* Width of the element */ flex-basis: calc(var(--width) / var(--columns) * 100%); } @media (min-width: 576px) { .column { --width: var(--width-tablet, var(--width-mobile, var(--width-default))); } } @media (min-width: 768px) { .column { --width: var(--width-desktop, var(--width-tablet, var(--width-mobile, var(--width-default)))); } }

See the Pen
#11 Building responsive features with CSS custom properties
by Miko?aj (@mikolajdobrucki)
on CodePen.

Reducing fallback chains

One thing that doesn’t look that great in our code is that feedback chains are getting longer and longer with every breakpoint. If we’d like to tackle this issue, we can change our approach to something like this:

.column { --columns: 12; /* Number of columns in the grid system */ --width: var(--width-mobile, 0); /* Width of the element */ flex-basis: calc(var(--width) / var(--columns) * 100%); } @media (min-width: 576px) { .column { --width-tablet: var(--width-mobile); --width: var(--width-tablet); } } @media (min-width: 768px) { .column { --width-desktop: var(--width-tablet); --width: var(--width-desktop); } }

See the Pen
#12 Building responsive features with CSS custom properties
by Miko?aj (@mikolajdobrucki)
on CodePen.

This code is doing exactly the same job but in a bit different way. Instead of creating a full fallback chain for each breakpoint, we set a value of each variable to the variable from the previous breakpoint as a default value.

Why so complicated?

It looks like we’ve done quite a lot of work to complete a relatively simple task. Why? The main answer is: to make the rest of our code simpler and more maintainable. In fact, we could build the same layout by using the techniques described in the previous part of this article:

.container { display: flex; flex-wrap: wrap; margin: 0 auto; max-width: 960px; } .column { --columns: 12; /* Number of columns in the grid system */ --width: 0; /* Default width of the element */ flex-basis: calc(var(--width) / var(--columns) * 100%); } .header { --width: 12; } .content { --width: 12; } .sidebar { --width: 12; } @media (min-width: 576px) { .content { --width: 6; } .sidebar { --width: 6; } } @media (min-width: 768px) { .content { --width: 8; } .sidebar { --width: 4; } }

In a small project, this approach could work perfectly well. For the more complex solutions, I would suggest considering a more scalable solution though.

Why should I bother anyway?

If the presented code is doing a very similar job to what we can accomplish with preprocessors such as Sass, why should we bother at all? Are custom properties any better? The answer, as usually, is: it depends. An advantage of using Sass is better browser support. However, using custom properties has a few perks too:

  1. It’s plain CSS. In other words, it’s a more standardized, dependable solution, independent from any third parties. No compiling, no package versions, no weird issues. It just works (apart from the browsers where it just doesn’t work).
  2. It’s easier to debug. That’s a questionable one, as one may argue that Sass provides feedback through console messages and CSS does not. However, you can’t view and debug preprocessed code directly in a browser, whilst working with CSS variables, all the code is available (and live!) directly in DevTools.
  3. It’s more maintainable. Custom properties allow us to do things simply impossible with any preprocessor. It allows us to make our variables more contextual and, therefore, more maintainable. Plus, they are selectable by JavaScript, something Sass variables are not.
  4. It’s more flexible. Notice, that the grid system we’ve built is extremely flexible. Would you like to use a 12-column grid on one page and a 15-column grid on another? Be my guest—it’s a matter of a single variable. The same code can be used on both pages. A preprocessor would require generating code for two separate grid systems.
  5. It takes less space. As long as the weight of CSS files is usually not the main bottleneck of page load performance, it still goes without saying that we should aim to optimize CSS files when possible. To give a better image of how much can be saved, I made a little experiment. I took the grid system from Bootstrap and rebuilt it from scratch with custom properties. The results are as follows: the basic configuration of the Bootstrap grid generates over 54KB of CSS whilst a similar grid made with custom properties is a mere 3KB. That’s a 94% difference! What is more, adding more columns to the Bootstrap grid makes the file even bigger. With CSS variables, we can use as many columns as we want without affecting the file size at all.

The files can be compressed to minimize the difference a bit. The gzipped Bootstrap grid takes 6.4KB in comparison to 0.9KB for the custom properties grid. This is still an 86% difference!

Performance of CSS variables

Summing up, using CSS custom properties has a lot of advantages. But, if we are making the browser do all the calculations that had been done by preprocessors, are we negatively affecting the performance of our site? It’s true that using custom properties and calc() functions will use more computing power. However, in cases similar to the examples we discussed in this article, the difference will usually be unnoticeable. If you’d like to learn more about this topic, I would recommend reading this excellent article by Lisi Linhart.

Not only grid systems

After all, understanding the ins and outs of custom properties may not be as easy as it seems. It will definitely take time, but it’s worth it. CSS variables can be a huge help when working on reusable components, design systems, theming and customizable solutions. Knowing how to deal with fallback values and undeclared variables may turn out to be very handy then.

Thanks for reading and good luck on your own journey with CSS custom properties!

The post Responsive Designs and CSS Custom Properties: Building a Flexible Grid System appeared first on CSS-Tricks.

Moving a Self-Hosted WordPress Site to WordPress.com

Css Tricks - Tue, 02/26/2019 - 5:23am

I have a habit of getting some hosting when I need a new WordPress site. That is, a self-installed, self-hosted WordPress.org site. That's served me well over the years. I like my control. But along with that control comes a certain level of extra responsibility that sometimes just isn't worth it.

That's the case for me now with my little blog Email is Good.

Right from the get-go, I knew I wanted Email is Good to be as absolutely simple as could be. At the moment, I can't prioritize a fancy custom design or really any specialized functionality at all. All I want is a simple, clean blog in which to publish blog posts. And as powerful and flexible as WordPress is, it's still extra good at that use case.

Email is Good uses an untouched, stock copy of the TwentySixteen theme.

I'd like to move it over to WordPress.com, so that I don't have to deal with hosting, upgrades, backups, security... it'll just host my simple blog and I can unburden myself of that little spoonful of technical debt.

Their docs for this are there, but a little on the light side, so I'll document my process here.

Set up the WordPress.com side first

There is a nice clean URL for kicking off a new WordPress.com site:

https://wordpress.com/start/

There isn't really a one-click just suck everything over in one shot system. Instead, you set up the site on WordPress.com, deal with the domain, and import the content. It might feel a little weird, but this first step is just kinda re-setting up the basics:

Deal with the domain

By "domain", I mean the URL that you may already own. I own "email-is-good.com" which is what I want to continue to use.

During setup you can buy a domain (or get a free one! They'll give you a wordpress.com or .blog subdomain), but since I'm moving a site here, I'll select the option that I already own the domain.

My domain name is already registered on GoDaddy.com. I could just leave the domain name there and map the domain over to WordPress.com. I think that's generally a smart thing to do, but I wanted to try what seems to be the default which is transferring it over to WordPress.com.

Part of the beauty of transferring the domain is there is no settings to screw up, as it will be handled by WordPress.com

I went through a process of basically re-registering the domain with WordPress.com.

In order to actually transfer the domain, I had to go to GoDaddy and "unlock" the domain as well as request a transfer authorization code.

If you're transferring a domain, it can take a little while.

The note on the page above tells me it might take a full week to complete. It took me one day less. I got the success email on February 18th instead of 19th.

I did have to "flip the switch", as the email suggests, to use the WordPress nameservers.

But before I did, I made sure the new WordPress.com site had all the old content!

Exporting Content & Media

There is an export tool baked right into WordPress. Find it under Tools.

You'll get an .xml file as output. Mine was called:

emailisgood.wordpress.2019-02-12.xml

Importing Content & Media

On the WordPress.com side, there is a big Import option right in the sidebar. In those options, there is a WordPress option to choose.

Drag and drop the .xml file there.

Mine was pretty quick, but I imagine it could take a while. You'll even get an email when it's done.

All my content and media made the journey just fine!

Clean Up

I had to do a little cleanup here and there to get the site exactly as it was. My site is so basic, it was hardly any work, but it's worth knowing you might have to mop up a little. For example, the site already had a contact page, so I had to nuke the one that was imported (which was using a contact form plugin I didn't need any more anyway) and make sure it was all functional.

Another thing that didn't make the trip to the new site was the widgets. I had a sidebar with some widgets that I had to re-build, but that was no big deal. I literally copy-pasted the content from them from the old site before I flipped the switch.

So now! I've ditched a pile of technical debt. No more worrying about my SSL certifiate. No more having to manually follow up with any hosting company about downtime. Performance is largely in the hands of someone else.

I just have a simple site where I can write write write.

Video!

If it's helpful for you to watch me talk all this out, I've put it on YouTube:

The post Moving a Self-Hosted WordPress Site to WordPress.com appeared first on CSS-Tricks.

iconsvg.xyz

Css Tricks - Mon, 02/25/2019 - 10:45am

There is a lot to like about Gaddafi Rusli's ICONSVG.

  1. It provides inline <svg>, which is the most generically useful way to deliver them, and probably how they should be used anyway. Each icon is a tiny amount of SVG and I'd bet they were all hand-golfed.
  2. They are all stroke-based, so they can be beefed up or slimmed down as needed.
  3. The stroke-linecap and stroke-linejoin properties can be adjusted, which presents an opportunity to make their edges sharper or more rounded. I often find icons that are close to what I want, but the weight isn't right or the edges are either too sharp or too round. This quick and easy configuration is awesome.

Direct Link to ArticlePermalink

The post iconsvg.xyz appeared first on CSS-Tricks.

Dealing with overflow and position: sticky;

Css Tricks - Mon, 02/25/2019 - 10:44am

Any overflow value other than visible and no height is the enemy of child elements with position: sticky;. It's like that element is ready to stick when the parent scrolls, but it never does because the height is unconstrained. Adding a fixed height can solve the issue, but that's not always desirable.

Dannie Vinther digs into a way of dealing with that. The end result is avoiding that situation all together by removing the element that wants to be sticky from the element that needs an overflow. But as soon as you do that, the elements no longer scroll together since they aren't siblings. The use case here is a table with sticky headers on vertical scrolling and allowing for horizontal scrolling as well. Dannie uses a script to sync the scroll positions.

Direct Link to ArticlePermalink

The post Dealing with overflow and position: sticky; appeared first on CSS-Tricks.

Responsive Designs and CSS Custom Properties: Defining Variables and Breakpoints

Css Tricks - Mon, 02/25/2019 - 5:22am

CSS custom properties (a.k.a. CSS variables) are becoming more and more popular. They finally reached decent browser support and are slowly making their way into various production environments. The popularity of custom properties shouldn’t come as a surprise, because they can be really helpful in numerous use cases, including managing color palettes, customizing components, and theming. But CSS variables can also be really helpful when it comes to responsive design.

Article Series:
  1. Defining Variables and Breakpoints (This Post)
  2. Building a Flexible Grid System

Let’s consider an <article> element with a heading and a paragraph inside:

<article class="post"> <h2 class="heading">Post's heading</h2> <p class="paragraph"> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Laudantium numquam adipisci recusandae officiis dolore tenetur, nisi, beatae praesentium, soluta ullam suscipit quas? </p> </article>

It’s a common scenario in such a case to change some sizes and dimensions depending on the viewport’s width. One way to accomplish this is by using media queries:

.post { padding: 0.5rem 1rem; margin: 0.5rem auto 1rem; } .heading { font-size: 2rem; } @media (min-width: 576px) { .post { padding: 1rem 2rem; margin: 1rem auto 2rem; } .heading { font-size: 3rem; } }

See the Pen
#1 Building responsive features with CSS custom properties
by Miko?aj (@mikolajdobrucki)
on CodePen.

Such an approach gives us an easy way to control CSS properties on different screen sizes. However, it may be hard to maintain as the complexity of a project grows. When using media queries, keeping code readable and DRY at the same time quite often turns out to be challenging.

The most common challenges when scaling this pattern include:

  • Repeated selectors: Apart from bloating code with multiple declarations, it also makes future refactoring more difficult, e.g. every time a class name changes it requires remembering to update it in multiple places.
  • Repeated properties: Notice that when overwriting CSS rules within media queries, it requires repeating the entire declaration (e.g. font-size: 3rem;) even though it’s just the value (3rem) that actually changes.
  • Repeated media queries: To keep responsive styles contextual, it’s a common practice to include the same media queries in multiple places, close to the styles they override. Unfortunately, it not only makes code heavier, but also might make breakpoints much harder to maintain. On the other hand, keeping all responsive styles in one place, away from their original declarations, may be very confusing: we end up with multiple references to the same elements sitting in completely different places.

We can argue that repeated declarations and queries shouldn’t be such a big deal with proper file compression enabled, at least as long as we’re referring to performance. We can also merge multiple queries and optimize your code with post-processing tools. But wouldn’t it be easier to avoid these issues altogether?

There’s a lot of ways to avoid the issues listed above. One of them, that we will explore in this article, is to use CSS custom properties.

Using CSS variables for property values

There are plenty of amazing articles on the web explaining the concept of CSS custom properties. If you haven’t got chance to get familiar with them yet, I would recommend starting with one of the beginner articles on this topic such as this awesome piece by Serg Hospodarets as we are not going to get into details of the basic usage in this article.

The most common way of utilizing CSS custom properties in responsive design is to use variables to store values that change inside of media queries. To accomplish this, declare a variable that holds a value that is supposed to change, and then reassign it inside of a media query:

:root { --responsive-padding: 1rem; } @media (min-width: 576px) { :root { --responsive-padding: 2rem; } } .foo { padding: var(--responsive-padding); }

Assigning variables to the :root selector is not always a good idea. Same as in JavaScript, having many global variables is considered a bad practice. In real life, try to declare the custom properties in the scope they will actually be used.

This way, we are avoiding multiple rules of the .foo class. We are also separating the logic (changing values) from the actual designs (CSS declarations). Adapting this approach in our example from above gives us the following CSS:

.post { --post-vertical-padding: 0.5rem; --post-horizontal-padding: 1rem; --post-top-margin: 0.5rem; --post-bottom-margin: 1rem; --heading-font-size: 2rem; } @media (min-width: 576px) { .post { --post-vertical-padding: 1rem; --post-horizontal-padding: 2rem; --post-top-margin: 1rem; --post-bottom-margin: 2rem; --heading-font-size: 3rem; } } .post { padding: var(--post-vertical-padding) var(--post-horizontal-padding); margin: var(--post-top-margin) auto var(--post-bottom-margin); } .heading { font-size: var(--heading-font-size); }

See the Pen
#2 Building responsive features with CSS custom properties
by Miko?aj (@mikolajdobrucki)
on CodePen.

Notice that the use of variables in shorthand properties (e.g. padding, margin or font) allow some very interesting repercussions. As custom properties may hold almost any value (more on this later), even an empty string, it’s unclear how the value of a shorthand property will be separated out into longhand properties that are used in the cascade later. For example, the auto used in the margin property above may turn out to be a top-and-bottom margin, a left-and-right margin, a top margin, a right margin, a bottom margin or a left margin — it all depends on the values of the custom properties around.

It’s questionable whether the code looks cleaner than the one from the previous example, but on a larger scale, it’s definitely more maintainable. Let’s try to simplify this code a bit now.

Notice that some values are repeated here. What if we try to merge duplicate variables together? Let’s consider the following alteration:

:root { --small-spacing: 0.5rem; --large-spacing: 1rem; --large-font-size: 2rem; } @media (min-width: 576px) { :root { --small-spacing: 1rem; --large-spacing: 2rem; --large-font-size: 3rem; } } .post { padding: var(--small-spacing) var(--large-spacing); margin: var(--small-spacing) auto var(--large-spacing); } .heading { font-size: var(--large-font-size); }

See the Pen
#3 Building responsive features with CSS custom properties
by Miko?aj (@mikolajdobrucki)
on CodePen.

It looks cleaner but is it actually better? Not necessarily. For the sake of flexibility and readability, this may not be the right solution in every case. We definitely shouldn’t merge some variables just because they accidentally turned out to hold the same values. Sometimes, as long as we’re doing this as a part of a well thought out system, it may help us simplify things and preserve consistency across the project. However, in other cases, such a manner may quickly prove to be confusing and problematic. Now, let’s take a look at yet another way we can approach this code.

Using CSS variables as multipliers

CSS custom properties are a fairly new feature to the modern web. One of the other awesome features that rolled out in the last years is the calc() function. It lets us perform real math operations in live CSS. In terms of the browser support, it’s supported in all browsers that support CSS custom properties.

calc() tends to play very nicely with CSS variables, making them even more powerful. This means we can both use calc() inside custom properties and custom properties inside calc()!

For example, the following CSS is perfectly valid:

:root { --size: 2; } .foo { --padding: calc(var(--size) * 1rem); /* 2 × 1rem = 2rem */ padding: calc(var(--padding) * 2); /* 2rem × 2 = 4rem */ }

Why does this matter to us and our responsive designs? It means that we can use a calc() function to alter CSS custom properties inside media queries. Let’s say we have a padding that should have a value of 5px on mobile and 10px on desktop. Instead of declaring this property two times, we can assign a variable to it and multiply it by two on larger screens:

:root { --padding: 1rem; --foo-padding: var(--padding); } @media (min-width: 576px) { :root { --foo-padding: calc(var(--padding) * 2); } } .foo { padding: var(--foo-padding); }

Looks fine, however all the values (--padding, calc(--padding * 2)) are away from their declaration (padding). The syntax may also be pretty confusing with two different padding variables (--padding and --foo-padding) and an unclear relationship between them.

To make things a bit clearer, let’s try to code it the other way around:

:root { --multiplier: 1; } @media (min-width: 576px) { :root { --multiplier: 2; } } .foo { padding: calc(1rem * var(--multiplier)); }

This way, we accomplished the same computed output with much cleaner code! So, instead of using a variable for an initial value of the property (1rem), a variable was used to store a multiplier (1 on small screens and 2 on larger screens). It also allows us to use the --multiplier variable in other declarations. Let’s apply this technique to paddings and margins in our previous snippet:

:root { --multiplier: 1; } @media (min-width: 576px) { :root { --multiplier: 2; } } .post { padding: calc(.5rem * var(--multiplier)) calc(1rem * var(--multiplier)); margin: calc(.5rem * var(--multiplier)) auto calc(1rem * var(--multiplier)); }

Now, let’s try to implement the same approach with typography. First, we’ll add another heading to our designs:

<h1 class="heading-large">My Blog</h1> <article class="post"> <h2 class="heading-medium">Post's heading</h2> <p class="paragraph"> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Laudantium numquam adipisci recusandae officiis dolore tenetur, nisi, beatae praesentium, soluta ullam suscipit quas? </p> </article>

With multiple text styles in place, we can use a variable to control their sizes too:

:root { --headings-multiplier: 1; } @media (min-width: 576px) { :root { --headings-multiplier: 3 / 2; } } .heading-medium { font-size: calc(2rem * var(--headings-multiplier)) } .heading-large { font-size: calc(3rem * var(--headings-multiplier)) }

You may have noticed that 3 / 2 is not a valid CSS value at all. Why does it not cause an error then? The reason is that the syntax for CSS variables is extremely forgiving, which means almost anything can be assigned to a variable, even if it’s not a valid CSS value for any existing CSS property. Declared CSS custom properties are left almost entirely un-evaluated until they are computed by a user agent in certain declarations. So, once a variable is used in a value of some property, this value will turn valid or invalid at the computed-value time.

Oh, and another note about that last note: in case you’re wondering, I used a value of 3 / 2 simply to make a point. In real life, it would make more sense to write 1.5 instead to make the code more readable.

Now, let’s take a look at the finished live example combining everything that we discussed above:

See the Pen
#4 Building responsive features with CSS custom properties
by Miko?aj (@mikolajdobrucki)
on CodePen.

Again, I would never advocate for combining calc() with custom properties to make the code more concise as a general rule. But I can definitely imagine scenarios in which it helps to keep code more organized and maintainable. This approach also allows the weight of CSS to be significantly reduced, when it’s used wisely.

In terms of readability, we can consider it more readable once the underlying rule is understood. It helps to explain the logic and relations between values. On the other hand, some may see it as less readable, because it’s tough to instantly read what a property holds as a value without first doing the math. Also, using too many variables and calc() functions at once may unnecessarily obscure code and make it harder to understand, especially for juniors and front-end developers who are not focused on CSS.

Conclusion

Summing up, there’s a lot of ways to use CSS custom properties in responsive design, definitely not limited to the examples shown above. CSS variables can be used simply to separate the values from the designs. They can also be taken a step further and be combined with some math. None of the presented approaches is better nor worse than the others. The sensibility of using them depends on the case and context.

Now that you know how CSS custom properties can be used in responsive design, I hope you will find a way to introduce them in your own workflow. Next up, we’re going to look at approaches for using them in reusable components and modules, so let's check that out.

The post Responsive Designs and CSS Custom Properties: Defining Variables and Breakpoints appeared first on CSS-Tricks.

Using CSS Grid the right way

Css Tricks - Fri, 02/22/2019 - 12:59pm

Violet Peña has shared her recommendations for using CSS Grid. They basically boil down to these high-level points:

  1. Use names instead of numbers for setting up our grid columns.
  2. fr should be our flexible unit of choice.
  3. 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:

.container { display: grid; grid-template-columns: [sidebar] 3fr [content] 4fr; }

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.

Direct Link to ArticlePermalink

The post Using CSS Grid the right way appeared first on CSS-Tricks.

Writing Animations That Bring Your Site to Life

Css Tricks - Fri, 02/22/2019 - 7:36am

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.

Here’s what we’re going to build together:

Live Demo GitHub Repo

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 CSS animation 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:

  1. Artists.vue: a grid of artists
  2. Tracks.vue: An artist image with a back button

If you wanna jump ahead a bit, here are some assets to work with:

  1. Images and sample data in JSON format.
  2. Content for the components

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:

const {x, y} = event.target.getBoundingClientRect()

...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.

gotoTracks(position, artistId) { this.$router.push({ name: 'tracks', params: { id: artistId, position: position } }) }

Here’s the relevant code from the repo to reference, in case you’re interested.

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.

const { x, y } = this.$route.params.position // padding-left const offsetLeft = 100 // padding-top const offsetTop = 30 // Set CSS custom property value document.documentElement.style.setProperty( '--translate', `translate(${x - offsetLeft}px, ${y - offsetTop}px) scale(0.792)` )

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).

.track { opacity: 0; transform: scale(0.7); animation: scale-up 1s ease forwards; } @keyframes scale-up { to { opacity: 1; 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:

.track { ... animation: slide-up 1.5s; } @keyframes slide-up { from { transform: translateY(140px); } }

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.

<svg @click="changeVolume"> <g :class="`level-${volumeLevel}`"> <path d="..."/> <!-- volume level 1 --> <path d="..."/> <!-- volume level 2 --> <path d="..."/> <!-- volume level 3 --> <polygon points="..."/> </g> </svg>

Based on this class, we can show and hide certain path elements as:

path { opacity: 0; transform-origin: left; transform: translateX(-5px) scale(0.6); transition: transform 0.25s, opacity 0.2s; } .level-1 path:first-child, .level-2 path:first-child, .level-2 path:nth-child(2), .level-3 path { opacity: 1; transform: none; } The animated volume control Second micro-interaction: The favorite icon

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.

@keyframes bounce { 0%, 100% { transform: none; } 30% { transform: scale(1.3); } 60% { transform: scale(0.9); } }

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.

@keyframes float-upwards { 0%, 100% { opacity: 0; } 50% { opacity: 0.7; } 50%, 100% { transform: translate(-1px, -5px); } } The animated favorite button Summing up

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.

The post Writing Animations That Bring Your Site to Life appeared first on CSS-Tricks.

Blobs!

Css Tricks - Thu, 02/21/2019 - 12:01pm

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.

Thank god for... (wait for it)... THE BLOBMAKER:

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:

See the Pen
CSS only morphing blob
by Monica Dinculescu (@notwaldorf)
on CodePen.

Or we can use a JavaScript library like KUTE.js to get all morph-y, like Heartbeat has done here:

See the Pen
Morphing shapes with KUTE.js
by Heartbeat.UA (@hbagency)
on CodePen.

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:

See the Pen
SVG blob mask
by ATCOM (@Atcom)
on CodePen.

We've only looked at SVG so far, but don't rule out <canvas>! Liam Egan has make this canvas-based blob downright jiggly:

See the Pen
Blob
by Liam Egan (@shubniggurath)
on CodePen.

Why not add a little physics to the party, like gravity, and let them blobs get squishy that way! Hakim El Hattab got it done here:

See the Pen
Blob
by Hakim El Hattab (@hakimel)
on CodePen.

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.

The post Blobs! appeared first on CSS-Tricks.

Deliver your best work with the help of monday.com

Css Tricks - Thu, 02/21/2019 - 11:58am

(This is a sponsored post.)

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.

Seriously, you'll wonder what you ever did without monday.com in your life once you've used it. It does everything any other project management tool can do — from task lists and milestones to budgets and human resources — but does one important thing that separates it from the rest: the personal touch that makes everyone on the team feel valuable, included and heard. That's tough to beat and unique to the project management landscape.

Like most things, seeing is believing, so give monday.com a try today. The first 14 days are on the house and will give you a feel for what makes it so great.

Try it Free

Direct Link to ArticlePermalink

The post Deliver your best work with the help of monday.com appeared first on CSS-Tricks.

CSS Variables + calc() + rgb() = Enforcing High Contrast Colors

Css Tricks - Thu, 02/21/2019 - 6:26am

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.

Here is an example using CSS variables:

:root { --red: 28; --green: 150; --blue: 130; --accessible-color: calc( ( ( (var(--red) * 299) + (var(--green) * 587) + (var(--blue) * 114) / 1000 ) - 128 ) * -1000 ); } .button { color: rgb( var(--accessible-color), var(--accessible-color), var(--accessible-color) ); background-color: rgb( var(--red), var(--green), var(--blue) ); }

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:

:root { --red: 28; --green: 150; --blue: 130; --accessible-color: calc( ( ( (var(--red) * 299) + (var(--green) * 587) + (var(--blue) * 114) ) - 128000 /* HIGHLIGHT */ ) * -1000 ); } .button { color: rgb( var(--accessible-color), var(--accessible-color), var(--accessible-color) ); background-color: rgb( var(--red), var(--green), var(--blue) ); }

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.

See the Pen
CSS Only Accessible Button
by Josh Bader (@joshbader)
on CodePen.

Putting this concept to practical use

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.

See the Pen
CSS Variable Accessible UI
by Josh Bader (@joshbader)
on CodePen.

There are other ways to do this

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!

Also, Robin Rendle explains how to use mix-blend-mode along with pseudo elements to automatically reverse text colors based on their background-color.

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.

The post CSS Variables + calc() + rgb() = Enforcing High Contrast Colors appeared first on CSS-Tricks.

Colorful Typographic Experiments

Css Tricks - Wed, 02/20/2019 - 1:05pm

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.

Codrin Pavel created a fascinating multi-color typeface called CSSans.

It's not a "font", because a font is a file, like "lato.woff2" or whatever. This is a CSS file, and you write in it like this:

<div class="cssans cssans--center"> <div class="cssans__accessible">Cool News</div> <div class="cssans__word"> <b class="cssans:C"></b> <b class="cssans:o"></b> <b class="cssans:o"></b> <b class="cssans:l"></b> </div> <div class="cssans__word"> <b class="cssans:N"></b> <b class="cssans:e"></b> <b class="cssans:w"></b> <b class="cssans:s"></b> </div> </div>

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.

Looks like the landing page was built in CodePen Projects!

This technique and its relationship with accessibility is pretty interesting and actually more relevant than you might think. In fact, it looks like Facebook uses a similar span technique to fight ad-blocking.

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...

  1. Use it quite a bit around the site for dynamic headlines
  2. Customize the colors to be perfect for you (ahead of time)
  3. 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:

See the Pen
START Pure CSS Lettering test 1
by Kenneth Ormandy (@kennethormandy)
on CodePen.

The post Colorful Typographic Experiments appeared first on CSS-Tricks.

<span>L</span><span>e</span><span>t</span><span>t</span><span>e</span><span>r</span><span>s</span>

Css Tricks - Wed, 02/20/2019 - 11:05am

Did you see this Facebook crap?

"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

— Mike Pan (@themikepan) February 6, 2019

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:

<!-- start: advertisement --> <div class="ad sponsor paid" id="ad-1" data-ad="true"> <div>Sponsor:</div> <a href="https://sponsor.com" rel="nofollow">Company</span> </div> <!-- end: advertisement -->

The good ones have been doing it for ages.

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.

It's totally solvable though!

I just read about how powerful aria-label is via Web Platform News, quoting Amelia Bellamy-Royds:

An aria-label attribute on a button or link effectively replaces the text content of that element with the new label.

It was cool to see that's what Lettering.js does by default! And Splitting.js is figuring out the best method for them, which involves aria-label.

Oh, and as ever, ::nth-letter() would be cool. 2018 recap of a 2011 request.

The post <span>L</span><span>e</span><span>t</span><span>t</span><span>e</span><span>r</span><span>s</span> appeared first on CSS-Tricks.

Diana Smith’s Top 5 CSS Properties She Uses to Produce CSS Art

Css Tricks - Wed, 02/20/2019 - 11:04am

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:

  1. border-radius
  2. box-shadow
  3. transform
  4. gradients
  5. 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-radius Without 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.

Direct Link to ArticlePermalink

The post Diana Smith’s Top 5 CSS Properties She Uses to Produce CSS Art appeared first on CSS-Tricks.

Social Cards as a Service

Css Tricks - Tue, 02/19/2019 - 5:19am

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:

const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://example.com'); await page.screenshot({path: 'example.png'}); await browser.close(); })();

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?

The first I saw of this idea was Drew McLellan's Dynamic Social Sharing Images. Drew wrote a script to fire up Puppeteer and get the job done.

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!

The URL is like this:

https://og-image.now.sh/I%20am%20Chris%20and%20I%20am%20**cool**%20la%20tee%20ding%20dong%20da..png?theme=light&md=1&fontSize=100px&images=https%3A%2F%2Fassets.zeit.co%2Fimage%2Fupload%2Ffront%2Fassets%2Fdesign%2Fhyper-color-logo.svg

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:

Which is inserted as meta:

<meta property="og:image" content="https://www.hawksworx.com/card-image/-blog-find-that-at-card.png">

I dug through Phil's repos, naturally, and found his little machine for doing it.

I'm madly envious of all this and need to get one set up for myself.

The post Social Cards as a Service appeared first on CSS-Tricks.

Don’t Get Clever with Login Forms

Css Tricks - Tue, 02/19/2019 - 5:18am

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.

Direct Link to ArticlePermalink

The post Don’t Get Clever with Login Forms appeared first on CSS-Tricks.

How @supports Works

Css Tricks - Mon, 02/18/2019 - 7:39am

CSS has a neat feature that allows us to test if the browser supports a particular property or property:value combination before applying a block of styles — like how a @media query matches when, say, the width of the browser window is narrower than some specified size and then the CSS within it takes effect. In the same spirit, the CSS inside this feature will take effect when the property:value pair being tested is supported in the current browser. That feature is called @supports and it looks like this:

@supports (display: grid) { .main { display: grid; } }

Why? Well, that's a bit tricky. Personally, I find don't need it all that regularly. CSS has natural fallback mechanisms such that if the browser doesn't understand a property:value combination, then it will ignore it and use something declared before it if there is anything, thanks to the cascade. Sometimes that can be used to deal with fallbacks and the end result is a bit less verbose. I'm certainly not a it's-gotta-be-the-same-in-every-browser kinda guy, but I'm also not a write-elaborate-fallbacks-to-get-close kinda guy either. I generally prefer a situation where a natural failure of a property:value doesn't do anything drastic to destroy functionality.

That said, @supports certainly has use cases! And as I found out while putting this post together, plenty of people use it for plenty of interesting situations.

A classic use case

The example I used in the intro is a classic one that you'll see used in lots of writing about this topic. Here it is a bit more fleshed out:

/* We're gonna write a fallback up here in a minute */ @supports (display: grid) { .photo-layout { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); grid-gap: 2rem; } }

Nice grid! Repeating and auto-filling columns is a sweet feature of CSS grid. But, of course, there are browsers that don't support grid, or don't support all the specific features of it that I'm using above there.

For example, iOS shipped support for CSS grid in version 10.2, but iOS has had flexbox support since version 7. That's a decent gap of people with older iOS devices that do support flexbox but not grid. I'm sure there are more example gaps like that, but you probably get the idea.

I was running on an older version of mobile safari and many many many many many sites were flat out broken that used grid

I’m waiting another year or so before messing about with it

— David Wells (@DavidWells) February 6, 2019

It may be acceptable to let the fallback for this be nothing, depending on the requirements. For example, vertically stacked block-level elements rather than a multi-column grid layout. That's often fine with me. But let's say it's not fine, like a photo gallery or something that absolutely needs to have some basic grid-like structure. In that case, starting with flexbox as the default and using @supports to apply grid features where they're supported may work better...

.photo-layout { display: flex; flex-wrap: wrap; > div { flex: 200px; margin: 1rem; } } @supports (display: grid) { .photo-layout { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); grid-gap: 2rem; > div { margin: 0; } } }

The "fallback" is the code outside of the @supports block (the properties above the block in the example above), and the grid code is either inside or after. The @supports block doesn't change any specificity, so we need the source order to help make sure the overrides work.

Notice I had to reset the margin on the divs inside the @supports block. That's the kind of thing I find a bit annoying. There is just enough crossover between the two scenarios that it requires being super aware of how they impact each other.

Doesn't that make you wish it could be entirely logically separated...

There is "not" logic in @supports blocks, but that doesn't mean it should always be used

Jen Simmons put this example in an article called Using Feature Queries in CSS a few years ago:

/* Considered a BAD PRACTICE, at least if you're supporting IE 11 and iOS 8 and older */ @supports not (display: grid) { /* Isolated code for non-support of grid */ } @supports (display: grid) { /* Isolated code for support of grid */ }

Notice the not operator in the first block. That's checking for browsers that do not support grid in order to apply certain styles to those browsers. The reason this approach is considered bad practice is that the browser support for @supports itself has to be considered!. That's what makes this so dang tricky.

It's very appealing to write code in logically separated @supports blocks like that because then it's starting from scratch each time and doesn't need to be overriding previous values and dealing with those logical mind-benders. But let's go back to the same iOS situation we considered before... @supports shipped in iOS in version 9 (right between when flexbox shipped in iOS 7 and grid shipped in iOS 10.2). That means any flexbox fallback code in a @supports block using the not operator to check for (display: grid) {} support wouldn't work in either iOS 7 or 8, meaning the fallback now needs a fallback from working in browsers it otherwise would have. Phew!

The big reason to reach for @supports is to account for very different implementations of something depending on feature support where it becomes easier to reason and distinguish between those implementations if the blocks of code are separated.

We'll probably get to a point where we can use mutually-exclusive blocks like that without worry. Speaking of which...

@supports is likely to be more useful over time.

Once @supports is supported in all browsers you need to support, then it's good to start using it more aggressively and without having to factor in the complication of considering whether @supports itself is supported. Here's the support grid on that:

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

DesktopChromeOperaFirefoxIEEdgeSafari2812.122No129Mobile / TabletiOS SafariOpera MobileOpera MiniAndroidAndroid ChromeAndroid Firefox9.0-9.246all4.47164

Basically, IE 11 and any iOS device stuck on iOS 8 are the pain points. If your requirements are already past those, then you're good to use @supports more freely.

The irony is that there hasn't been a ton of CSS features shipping that have big clear @supports use cases — but there are some! Apparently, it's possible to test new fancy stuff like Houdini:

Using it on my wedding website to check for Houdini support &#x1f3a9;&#x1f430;

— Sam Richard (@Snugug) February 6, 2019

(I'm not sure entirely what you'd put in the @supports block to do that. Has anyone else done this?)

When @supports isn't doing anything useful

I've seen a good amount of @supports uses in the wild where the end result is exactly as it would be without using it. For example...

@supports (transform: rotate(5deg)) { .avatar { transform: rotate(5deg); } }

On some level, that makes perfect logical sense. If transforms are supported, use them. But it's unnecessary if nothing different is happening in a non-support scenario. In this case, the transform can fail without the @supports block and the result is the same.

Here's another example of that shaking out.

There are browser extensions for playing with @supports

There are two of them!

They are both centered around the idea that we can write @supports blocks in CSS and then toggle them on and off as if we're looking at a rendering of the code in a browser that does or doesn't support that feature.

Here's a video of Keith's tool applied to the scenario using grid with a flexbox fallback:

This is fun to play with and is very neat tech. But in this exact scenario, if I was able to pull off the layout identically with flexbox, then I'd probably just do that and save that little bit of technical debt.

Ire's tool, which she wrote about in the article Creating The Feature Queries Manager DevTools Extension, has a slightly different approach in that it shows the feature queries that you actually wrote in your CSS and provides toggles to flip them on and off. I don't think it works through iframes though, so I popped open Debug Mode to use it on CodePen.

More real world use cases for @supports

Here's one from Erik Vorhes. He's styling some custom checkboxes and radio buttons here, but wraps all of it in a @supports block. None of the styling gets applied unless the block passes the support check.

@supports (transform: rotate(1turn)) and (opacity: 0) { /* all the styling for Erik's custom checkboxes and radio buttons */ }

Here are several more I've come across:

  • Joe Wright and Tiago Nunes mentioned using it for position: sticky;. I'd love to see a demo here! As in, where you go for position: sticky;, but then have to do something different besides let it fail for a non-supporting browser.
  • Keith Grant and Matthias Ott mention using it for object-fit: contain;. Matthias has a demo where positioning trickery is used to make an image sort of fill a container, which is then made easier and better through that property when it's available.
  • Ryan Filler mentions using it for mix-blend-mode. His example sets more opacity on an element, but if mix-blend-mode is supported, it uses a bit less and that property which can have the effect of seeing through an element on its own.
  • .thing { opacity: 0.5; } @supports (mix-blend-mode: multiply) { .thing { mix-blend-mode: multiply; opacity: 0.75; } }
  • Rik Schennink mentioned the backdrop-filter property. He says, "when it's supported the opacity of the background color often needs some fine tuning."
  • Nour Saud mentioned it can be used to detect Edge through a specific vendor-prefixed property: @supports (-ms-ime-align:auto) { }.
  • Amber Weinberg mentioned using it for clip-path because adjusting the sizing or padding of an element will accommodate when clipping is unavailable.
  • Ralph Holzmann mentioned using it to test for that "notch" stuff (environment variables).
  • Stacy Kvernmo mentioned using it for the variety of properties needed for drop capping characters. Jen Simmons mentions this use case in her article as well. There is an initial-letter CSS property that's pretty fantastic for drop caps, but is used in conjunction with other properties that you may not want to apply at all if initial-letter isn't supported (or if there's a totally different fallback scenario).

Here's a bonus one from Nick Colley that's not @supports, but @media instead! The spirit is the same. It can prevent that "stuck" hover state on touch devices like this:

@media (hover: hover) { a:hover { background: yellow; } } Logic in @supports

Basic:

@supports (initial-letter: 4) { }

Not:

@supports not (initial-letter: 4) { }

And:

@supports (initial-letter: 4) and (transform: scale(2)) { }

Or:

@supports (initial-letter: 4) or (-webkit-initial-letter: 4) { }

Combos:

@supports ((display: -webkit-flex) or (display: -moz-flex) or (display: flex)) and (-webkit-appearance: caret) { } JavaScript Variant

JavaScript has an API for this. To test if it exists...

if (window.CSS && window.CSS.supports) { // Apparently old Opera had a weird implementation, so you could also do: // !!((window.CSS && window.CSS.supports) || window.supportsCSS || false) }

To use it, either pass the property to it in one param and the value in another:

const supportsGrid = CSS.supports("display", "grid");

...or give it all in one string mirroring the CSS syntax:

const supportsGrid = CSS.supports("(display: grid)"); Selector testing

At the time of this writing, only Firefox supports this sort of testing (behind an experimental flag), but there is a way to test the support of selectors with @supports. MDN's demo:

@supports selector(A > B) { } You?

Of course, we'd love to see Pens of @supports use cases in the comments. So share 'em!

The post How @supports Works appeared first on CSS-Tricks.

instant.page

Css Tricks - Mon, 02/18/2019 - 7:25am

instant.page is a pretty cool project from Alexandre Dieulot. Alexandre has been at this idea for half a decade now, as InstantClick is his and is essentially the same exact idea.

The idea is that there is a significant delay between hovering over a link and clicking that link. Say it takes you 300ms of delay. That 300ms could have been spent preloading the next page. And if you do use that time preloading, that page loads that much faster.

This new project makes use of newer tech to get it done. It's hardly any code., the core of which is appending a <link rel="prefetch" href=""> to the document of the link you're about to click/touch.

The page encourages you to hotlink the script, which means possible cache-hits in case you've already visited a page using this. It's not risky in the way other third-party JavaScript can be because the integrity attribute means that if you trust the code as it is now, it can't ever change unless you change that attribute along with it. It also cleverly uses the type="module" to prevent it from loading anything in browsers that don't support prefetching anyway.

Still, you could self-host it if you wanted. I have no idea who's ponying up the for the bandwidth here, so another risk is a hung script should it stop responding one day.

You could argue that it doesn't do the prefetching as absolutely responsibly as it could. Google's similar quick link library (which we covered here) does two interesting things in which to attempt to be more responsible with prefetching: 1) wait for requestIdleCallback and 2) respects info from navigator.connection, like a user enabling data-saver mode.

Direct Link to ArticlePermalink

The post instant.page appeared first on CSS-Tricks.

Syndicate content
©2003 - Present Akamai Design & Development.