Chris’ Corner: Little Useful Websites

Category Image 052

I came across Alexey Ardov’s work the other day. Looks like the color bug hit him pretty hard. I first saw this playground:

It’s awfully cool. I like seeing color palettes presented in the context of UI like that. Sometimes it’s hard to picture how it all might come together if colors are looked at too abstractly. It doesn’t exactly have an export tool, but a bunch of CSS custom properties are barfed out into a style attribute on the <body> if you were so inclined to use them for something.

Of course I thought: HSL is nicely used here, but what about the HDR color formats?! Seems like a good opportunity to set up P3 colors and non-P3 color fallbacks. I don’t think this fact is lost on Alexey, as they have lots more color experiments they have built. For example, this visualizer for looking at color models, which then it looks like got an upgrade to visualize more models (and gamuts).

I like looking at those things as they are a reminder of just how designed these color spaces are and how deep the rabbit hole can go. Before you know it, you’re designing extremely sophisticated accessible color palette generation tools.


Looking at these one-off single-purpose websites always puts me in the mood to share more. Aren’t you lucky that I save links to new ones that I see just for times like this.

CSS-Pattern

Temani Afif’s pattern site has some pretty sophisticated backgrounds that are done just with CSS backgrounds. Reminds me of Lea’s take on this from years ago. A grand tradition of CSS wizards.

Very easy to paste on into a Pen.

SpaceBadgers

Those little badge graphics that are super common at the top of GitHub repos, created with a super clean URL format.

Oh and hey they look great small but you can make them as big as you want and because they are SVG they scale up nicely.


Theme Toggles

Need a neat little animated toggle for Light Mode / Dark Mode? This site has a whole bunch of them:

Wasn’t much to pluck one over to a Pen, in case you need a reference there. I saw a little controversy on this as one of the usage options is as a <div>, which of course is not an interactive element. I’m not sure that’s fair, as you might use this as a visual adornment next to an interactive button, for example. And the React exports use <button> nicely.


Tree

I’m sorry I can’t explain it, but sometimes you have to update intended text to have a bunch of extra special ASCII characters that better represent a file tree.


Custom Shape Dividers

In the rectangular world of web design, sometimes just what you need is something… not rectangular.

The site provides SVG, HTML, and CSS for you to copy out, which, I’m sure you’re aware, plunking over to CodePen to play with is a snap. Gosh, isn’t CodePen useful? You should go PRO.

Chris’ Corner: Baseline

Category Image 052

At this latest Google I/O, Rachel Andrew introduced a new concept they are spearheading called Baseline. It’s a visual thing to help developers understand browser support for features better. Here’s one:

It’s not a Google-owned-website only thing, as you can see here on an MDN page.

It’s essentially a simplified browser support chart, featuring only Chrome, Edge, Firefox, and Safari. I’d argue Edge is just taking up space there as it’s-just-Chrome when it comes to web platform feature support, but Edge is still contributing to web platform stuff at a high enough level I think it’s probably a fair shoulder rub.

How do they get away with just a green-checkmark-or-not for browsers? They say it’s because we’ve reached the point where all the major browsers are now evergreen, as in, users don’t even have to update themselves, updates just arrive, so nobody has to think about versions much anymore. Sorta true, sorta not.

Presumably, it can also tell users when cross-browser support isn’t there yet, but I cannot find a single example of this. Presumably there is some red-ness and ❌ stuff happening. It’s tricky though isn’t it? I love the new View Transitions stuff (examples), but the main blog post on it doesn’t have a Baseline thingy. If it did, it would show that only Chrome has this feature, which would, I suppose, inform developers that the feature isn’t really ready to use. But is that true? Not really. If we avoid as much nuance as we possibly can with browser support, it should still be at least a three-answer game:

  1. You can use it.
  2. You can use it (but only with polyfills or progressive enhancement).
  3. You can not use it.

Baseline feels more YES or NO to me, avoiding that really useful middle answer which is perfect for even cutting-edge stuff like View Transitions.

It’s also tricky to know you’re looking at the correct thing. Take Una’s blog post about Style Queries in CSS, a brand new thing. The Baseline at the top is all green good-to-go. But Style Queries are definitely not all-green good-to-go. That Baseline is talking about container queries not style queries, and that is entirely not obvious at a glance. Gonna be tricky to get all this right.

I am pretty stoked about this though:

We’ll be providing widgets that you can use on your own articles or libraries, indicating support for the Baseline feature set.

The Can I Use site is used now by tons of developers (and also gets much of it’s data set from MDN, just like Baseline does). I always thought it was weird they didn’t offer their own lightweight embeds for any site to use. Way back when, Ire Aderinokun created The CanIUse Embed which was awesome but I don’t think it was ever updated for the MDN-data-only charts. Maybe Baseline can be a good and official version of embeddable browser support charts. I would have used them at CSS-Tricks (probably) if they existed.

What they should do is make a Web Component! Wouldn’t it be cool to see like:

<baseline-support feature="grid"></baseline-support>

And that would spit out what web.dev and MDN are essentially showing? Ship it. Then everybody benefits. Here’s another great article on Style Queries. Sure would be nice to see right at the top what kind of support we’re looking at.

Modern CSS Layouts: You Might Not Need A Framework For That

Category Image 052

Establishing layouts in CSS is something that we, as developers, often delegate to whatever framework we’re most comfortable using. And even though it’s possible to configure a framework to get just what we need out of it, how often have you integrated an entire CSS library simply for its layout features? I’m sure many of us have done it at some point, dating back to the days of 960.gs, Bootstrap, Susy, and Foundation.

Modern CSS features have significantly cut the need to reach for a framework simply for its layout. Yet, I continue to see it happen. Or, I empathize with many of my colleagues who find themselves re-creating the same Grid or Flexbox layout over and over again.

In this article, we will gain greater control over web layouts. Specifically, we will create four CSS classes that you will be able to take and use immediately on just about any project or place where you need a particular layout that can be configured to your needs.

While the concepts we cover are key, the real thing I want you to take away from this is the confidence to use CSS for those things we tend to avoid doing ourselves. Layouts used to be a challenge on the same level of styling form controls. Certain creative layouts may still be difficult to pull off, but the way CSS is designed today solves the burdens of the established layout patterns we’ve been outsourcing and re-creating for many years.

What We’re Making

We’re going to establish four CSS classes, each with a different layout approach. The idea is that if you need, say, a fluid layout based on Flexbox, you have it ready. The same goes for the three other classes we’re making.

And what exactly are these classes? Two of them are Flexbox layouts, and the other two are Grid layouts, each for a specific purpose. We’ll even extend the Grid layouts to leverage CSS Subgrid for when that’s needed.

Within those two groups of Flexbox and Grid layouts are two utility classes: one that auto-fills the available space — we’re calling these “fluid” layouts — and another where we have greater control over the columns and rows — we’re calling these “repeating” layouts.

Finally, we’ll integrate CSS Container Queries so that these layouts respond to their own size for responsive behavior rather than the size of the viewport. Where we’ll start, though, is organizing our work into Cascade Layers, which further allow you to control the level of specificity and prevent style conflicts with your own CSS.

Setup: Cascade Layers & CSS Variables

A technique that I’ve used a few times is to define Cascade Layers at the start of a stylesheet. I like this idea not only because it keeps styles neat and organized but also because we can influence the specificity of the styles in each layer by organizing the layers in a specific order. All of this makes the utility classes we’re making easier to maintain and integrate into your own work without running into specificity battles.

I think the following three layers are enough for this work:

@layer reset, theme, layout;

Notice the order because it really, really matters. The reset layer comes first, making it the least specific layer of the bunch. The layout layer comes in at the end, making it the most specific set of styles, giving them higher priority than the styles in the other two layers. If we add an unlayered style, that one would be added last and thus have the highest specificity.

Related: “Getting Started With Cascade Layers” by Stephanie Eckles.

Let’s briefly cover how we’ll use each layer in our work.

Reset Layer

The reset layer will contain styles for any user agent styles we want to “reset”. You can add your own resets here, or if you already have a reset in your project, you can safely move on without this particular layer. However, do remember that un-layered styles will be read last, so wrap them in this layer if needed.

I’m just going to drop in the popular box-sizing declaration that ensures all elements are sized consistently by the border-box in accordance with the CSS Box Model.

@layer reset {
  *,
  *::before,
  *::after {
    box-sizing: border-box;
  }

  body {
    margin: 0;
  }
}

Theme Layer

This layer provides variables scoped to the :root element. I like the idea of scoping variables this high up the chain because layout containers — like the utility classes we’re creating — are often wrappers around lots of other elements, and a global scope ensures that the variables are available anywhere we need them. That said, it is possible to scope these locally to another element if you need to.

Now, whatever makes for “good” default values for the variables will absolutely depend on the project. I’m going to set these with particular values, but do not assume for a moment that you have to stick with them — this is very much a configurable system that you can adapt to your needs.

Here are the only three variables we need for all four layouts:

@layer theme {
  :root {
    --layout-fluid-min: 35ch;
    --layout-default-repeat: 3;
    --layout-default-gap: 3vmax;
  }
}

In order, these map to the following:

Notice: The variables are prefixed with layout-, which I’m using as an identifier for layout-specific values. This is my personal preference for structuring this work, but please choose a naming convention that fits your mental model — naming things can be hard!

Layout Layer

This layer will hold our utility class rulesets, which is where all the magic happens. For the grid, we will include a fifth class specifically for using CSS Subgrid within a grid container for those possible use cases.

@layer layout {  
  .repeating-grid {}
  .repeating-flex {}
  .fluid-grid {}
  .fluid-flex {}

  .subgrid-rows {}
}

Now that all our layers are organized, variables are set, and rulesets are defined, we can begin working on the layouts themselves. We will start with the “repeating” layouts, one based on CSS Grid and the other using Flexbox.

Repeating Grid And Flex Layouts

I think it’s a good idea to start with the “simplest” layout and scale up the complexity from there. So, we’ll tackle the “Repeating Grid” layout first as an introduction to the overarching technique we will be using for the other layouts.

Repeating Grid

If we head into the @layout layer, that’s where we’ll find the .repeating-grid ruleset, where we’ll write the styles for this specific layout. Essentially, we are setting this up as a grid container and applying the variables we created to it to establish layout columns and spacing between them.

.repeating-grid {
  display: grid;
  grid-template-columns: repeat(var(--layout-default-repeat), 1fr);
  gap: var(--layout-default-gap);
}

It’s not too complicated so far, right? We now have a grid container with three equally sized columns that take up one fraction (1fr) of the available space with a gap between them.

This is all fine and dandy, but we do want to take this a step further and turn this into a system where you can configure the number of columns and the size of the gap. I’m going to introduce two new variables scoped to this grid:

  • --_grid-repeat: The number of grid columns.
  • --_repeating-grid-gap: The amount of space between grid items.

Did you notice that I’ve prefixed these variables with an underscore? This was actually a JavaScript convention to specify variables that are “private” — or locally-scoped — before we had const and let to help with that. Feel free to rename these however you see fit, but I wanted to note that up-front in case you’re wondering why the underscore is there.

.repeating-grid {
  --_grid-repeat: var(--grid-repeat, var(--layout-default-repeat));
  --_repeating-grid-gap: var(--grid-gap, var(--layout-default-gap));

  display: grid;
  grid-template-columns: repeat(var(--layout-default-repeat), 1fr);
  gap: var(--layout-default-gap);
}

Notice: These variables are set to the variables in the @theme layer. I like the idea of assigning a global variable to a locally-scoped variable. This way, we get to leverage the default values we set in @theme but can easily override them without interfering anywhere else the global variables are used.

Now let’s put those variables to use on the style rules from before in the same .repeating-grid ruleset:

.repeating-grid {
  --_grid-repeat: var(--grid-repeat, var(--layout-default-repeat));
  --_repeating-grid-gap: var(--grid-gap, var(--layout-default-gap));

  display: grid;
  grid-template-columns: repeat(var(--_grid-repeat), 1fr);
  gap: var(--_repeating-grid-gap);
}

What happens from here when we apply the .repeating-grid to an element in HTML? Let’s imagine that we are working with the following simplified markup:

<section class="repeating-grid">
  <div></div>
  <div></div>
  <div></div>
</section>

If we were to apply a background-color and height to those divs, we would get a nice set of boxes that are placed into three equally-sized columns, where any divs that do not fit on the first row automatically wrap to the next row.

Time to put the process we established with the Repeating Grid layout to use in this Repeating Flex layout. This time, we jump straight to defining the private variables on the .repeating-flex ruleset in the @layout layer since we already know what we’re doing.

.repeating-flex {
  --_flex-repeat: var(--flex-repeat, var(--layout-default-repeat));
  --_repeating-flex-gap: var(--flex-gap, var(--layout-default-gap));
}

Again, we have two locally-scoped variables used to override the default values assigned to the globally-scoped variables. Now, we apply them to the style declarations.

.repeating-flex {
  --_flex-repeat: var(--flex-repeat, var(--layout-default-repeat));
  --_repeating-flex-gap: var(--flex-gap, var(--layout-default-gap));

  display: flex;
  flex-wrap: wrap;
  gap: var(--_repeating-flex-gap);
}

We’re only using one of the variables to set the gap size between flex items at the moment, but that will change in a bit. For now, the important thing to note is that we are using the flex-wrap property to tell Flexbox that it’s OK to let additional items in the layout wrap into multiple rows rather than trying to pack everything in a single row.

But once we do that, we also have to configure how the flex items shrink or expand based on whatever amount of available space is remaining. Let’s nest those styles inside the parent ruleset:

.repeating-flex {
  --_flex-repeat: var(--flex-repeat, var(--layout-default-repeat));
  --_repeating-flex-gap: var(--flex-gap, var(--layout-default-gap));

  display: flex;
  flex-wrap: wrap;
  gap: var(--_repeating-flex-gap);

  > * {
    flex: 1 1 calc((100% / var(--_flex-repeat)) - var(--_gap-repeater-calc));
  }
}

If you’re wondering why I’m using the universal selector (*), it’s because we can’t assume that the layout items will always be divs. Perhaps they are <article> elements, <section>s, or something else entirely. The child combinator (>) ensures that we’re only selecting elements that are direct children of the utility class to prevent leakage into other ancestor styles.

The flex shorthand property is one of those that’s been around for many years now but still seems to mystify many of us. Before we unpack it, did you also notice that we have a new locally-scoped --_gap-repeater-calc variable that needs to be defined? Let’s do this:

.repeating-flex {
  --_flex-repeat: var(--flex-repeat, var(--layout-default-repeat));
  --_repeating-flex-gap: var(--flex-gap, var(--layout-default-gap));

  /* New variables */
  --_gap-count: calc(var(--_flex-repeat) - 1);
  --_gap-repeater-calc: calc(
    var(--_repeating-flex-gap) / var(--_flex-repeat) * var(--_gap-count)
  );

  display: flex;
  flex-wrap: wrap;
  gap: var(--_repeating-flex-gap);

  > * {
    flex: 1 1 calc((100% / var(--_flex-repeat)) - var(--_gap-repeater-calc));
  }
}

Whoa, we actually created a second variable that --_gap-repeater-calc can use to properly calculate the third flex value, which corresponds to the flex-basis property, i.e., the “ideal” size we want the flex items to be.

If we take out the variable abstractions from our code above, then this is what we’re looking at:

.repeating-flex {
  display: flex;
  flex-wrap: wrap;
  gap: 3vmax

  > * {
    flex: 1 1 calc((100% / 3) - calc(3vmax / 3 * 2));
  }
}

Hopefully, this will help you see what sort of math the browser has to do to size the flexible items in the layout. Of course, those values change if the variables’ values change. But, in short, elements that are direct children of the .repeating-flex utility class are allowed to grow (flex-grow: 1) and shrink (flex-shrink: 1) based on the amount of available space while we inform the browser that the initial size (i.e., flex-basis) of each flex item is equal to some calc()-ulated value.

Because we had to introduce a couple of new variables to get here, I’d like to at least explain what they do:

  • --_gap-count: This stores the number of gaps between layout items by subtracting 1 from --_flex-repeat. There’s one less gap in the number of items because there’s no gap before the first item or after the last item.
  • --_gap-repeater-calc: This calculates the total gap size based on the individual item’s gap size and the total number of gaps between items.

From there, we calculate the total gap size more efficiently with the following formula:

calc(var(--_repeating-flex-gap) / var(--_flex-repeat) * var(--_gap-count))

Let’s break that down further because it’s an inception of variables referencing other variables. In this example, we already provided our repeat-counting private variable, which falls back to the default repeater by setting the --layout-default-repeat variable.

This sets a gap, but we’re not done yet because, with flexible containers, we need to define the flex behavior of the container’s direct children so that they grow (flex-grow: 1), shrink (flex-shrink: 1), and with a flex-basis value that is calculated by multiplying the repeater by the total number of gaps between items.

Next, we divide the individual gap size (--_repeating-flex-gap) by the number of repetitions (--_flex-repeat)) to equally distribute the gap size between each item in the layout. Then, we multiply that gap size value by one minus the total number of gaps with the --_gap-count variable.

And that concludes our repeating grids! Pretty fun, or at least interesting, right? I like a bit of math.

Before we move to the final two layout utility classes we’re making, you might be wondering why we want so many abstractions of the same variable, as we start with one globally-scoped variable referenced by a locally-scoped variable which, in turn, can be referenced and overridden again by yet another variable that is locally scoped to another ruleset. We could simply work with the global variable the whole time, but I’ve taken us through the extra steps of abstraction.

I like it this way because of the following:

  1. I can peek at the HTML and instantly see which layout approach is in use: .repeating-grid or .repeating-flex.
  2. It maintains a certain separation of concerns that keeps styles in order without running into specificity conflicts.

See how clear and understandable the markup is:

<section class="repeating-flex footer-usps">
  <div></div>
  <div></div>
  <div></div>
</section>

The corresponding CSS is likely to be a slim ruleset for the semantic .footer-usps class that simply updates variable values:

.footer-usps {
  --flex-repeat: 3;
  --flex-gap: 2rem;
}

This gives me all of the context I need: the type of layout, what it is used for, and where to find the variables. I think that’s handy, but you certainly could get by without the added abstractions if you’re looking to streamline things a bit.

Fluid Grid And Flex Layouts

All the repeating we’ve done until now is fun, and we can manipulate the number of repeats with container queries and media queries. But rather than repeating columns manually, let’s make the browser do the work for us with fluid layouts that automatically fill whatever empty space is available in the layout container. We may sacrifice a small amount of control with these two utilities, but we get to leverage the browser’s ability to “intelligently” place layout items with a few CSS hints.

Fluid Grid

Once again, we’re starting with the variables and working our way to the calculations and style rules. Specifically, we’re defining a variable called --_fluid-grid-min that manages a column’s minimum width.

Let’s take a rather trivial example and say we want a grid column that’s at least 400px wide with a 20px gap. In this situation, we’re essentially working with a two-column grid when the container is greater than 820px wide. If the container is narrower than 820px, the column stretches out to the container’s full width.

If we want to go for a three-column grid instead, the container’s width should be about 1240px wide. It’s all about controlling the minimum sizing values in the gap.

.fluid-grid {
  --_fluid-grid-min: var(--fluid-grid-min, var(--layout-fluid-min));
  --_fluid-grid-gap: var(--grid-gap, var(--layout-default-gap));
}

That establishes the variables we need to calculate and set styles on the .fluid-grid layout. This is the full code we are unpacking:

 .fluid-grid {
  --_fluid-grid-min: var(--fluid-grid-min, var(--layout-fluid-min));
  --_fluid-grid-gap: var(--grid-gap, var(--layout-default-gap));

  display: grid;
  grid-template-columns: repeat(
    auto-fit,
    minmax(min(var(--_fluid-grid-min), 100%), 1fr)
  );
  gap: var(--_fluid-grid-gap);
}

The display is set to grid, and the gap between items is based on the --fluid-grid-gap variable. The magic is taking place in the grid-template-columns declaration.

This grid uses the repeat() function just as the .repeating-grid utility does. By declaring auto-fit in the function, the browser automatically packs in as many columns as it possibly can in the amount of available space in the layout container. Any columns that can’t fit on a line simply wrap to the next line and occupy the full space that is available there.

Then there’s the minmax() function for setting the minimum and maximum width of the columns. What’s special here is that we’re nesting yet another function, min(), within minmax() (which, remember, is nested in the repeat() function). This a bit of extra logic that sets the minimum width value of each column somewhere in a range between --_fluid-grid-min and 100%, where 100% is a fallback for when --_fluid-grid-min is undefined or is less than 100%. In other words, each column is at least the full 100% width of the grid container.

The “max” half of minmax() is set to 1fr to ensure that each column grows proportionally and maintains equally sized columns.

See the Pen Fluid grid [forked] by utilitybend.

That’s it for the Fluid Grid layout! That said, please do take note that this is a strong grid, particularly when it is combined with modern relative units, e.g. ch, as it produces a grid that only scales from one column to multiple columns based on the size of the content.

Fluid Flex

We pretty much get to re-use all of the code we wrote for the Repeating Flex layout for the Fluid Flex layout, but only we’re setting the flex-basis of each column by its minimum size rather than the number of columns.

.fluid-flex {
  --_fluid-flex-min: var(--fluid-flex-min, var(--layout-fluid-min));
  --_fluid-flex-gap: var(--flex-gap, var(--layout-default-gap));

  display: flex;
  flex-wrap: wrap;
  gap: var(--_fluid-flex-gap);

  > * {
    flex: 1 1 var(--_fluid-flex-min);
  }
}

That completes the fourth and final layout utility — but there’s one bonus class we can create to use together with the Repeating Grid and Fluid Grid utilities for even more control over each layout.

Optional: Subgrid Utility

Subgrid is handy because it turns any grid item into a grid container of its own that shares the parent container’s track sizing to keep the two containers aligned without having to redefine tracks by hand. It’s got full browser support and makes our layout system just that much more robust. That’s why we can set it up as a utility to use with the Repeating Grid and Fluid Grid layouts if we need any of the layout items to be grid containers for laying out any child elements they contain.

Here we go:

.subgrid-rows {
  > * {
    display: grid;
    gap: var(--subgrid-gap, 0);
    grid-row: auto / span var(--subgrid-rows, 4);
    grid-template-rows: subgrid;
  }
}

We have two new variables, of course:

  • --subgrid-gap: The vertical gap between grid items.
  • --subgrid-rows The number of grid rows defaulted to 4.

We have a bit of a challenge: How do we control the subgrid items in the rows? I see two possible methods.

Method 1: Inline Styles

We already have a variable that can technically be used directly in the HTML as an inline style:

<section class="fluid-grid subgrid-rows" style="--subgrid-rows: 4;">
  <!-- items -->
</section>

This works like a charm since the variable informs the subgrid how much it can grow.

Method 2: Using The :has() Pseudo-Class

This approach leads to verbose CSS, but sacrificing brevity allows us to automate the layout so it handles practically anything we throw at it without having to update an inline style in the markup.

Check this out:

.subgrid-rows {
  &:has(> :nth-child(1):last-child) { --subgrid-rows: 1; }
  &:has(> :nth-child(2):last-child) { --subgrid-rows: 2; }
  &:has(> :nth-child(3):last-child) { --subgrid-rows: 3; }
  &:has(> :nth-child(4):last-child) { --subgrid-rows: 4; }
  &:has(> :nth-child(5):last-child) { --subgrid-rows: 5; }
  /* etc. */

  > * {
    display: grid;
    gap: var(--subgrid-gap, 0);
    grid-row: auto / span var(--subgrid-rows, 5);
    grid-template-rows: subgrid;
  }
}

The :has() selector checks if a subgrid row is the last child item in the container when that item is either the first, second, third, fourth, fifth, and so on item. For example, the second declaration:

&:has(> :nth-child(2):last-child) { --subgrid-rows: 2; }

…is pretty much saying, “If this is the second subgrid item and it happens to be the last item in the container, then set the number of rows to 2.”

Whether this is too heavy-handed, I don’t know; but I love that we’re able to do it in CSS.

The final missing piece is to declare a container on our children. Let’s give the columns a general class name, .grid-item, that we can override if we need to while setting each one as a container we can query for the sake of updating its layout when it is a certain size (as opposed to responding to the viewport’s size in a media query).

:is(.fluid-grid:not(.subgrid-rows),
.repeating-grid:not(.subgrid-rows),
.repeating-flex, .fluid-flex) {
    > * {
    container: var(--grid-item-container, grid-item) / inline-size;
  }
}

That’s a wild-looking selector, but the verbosity is certainly kept to a minimum thanks to the :is() pseudo-class, which saves us from having to write this as a larger chain selector. It essentially selects the direct children of the other utilities without leaking into .subgrid-rows and inadvertently selecting its direct children.

The container property is a shorthand that combines container-name and container-type into a single declaration separated by a forward slash (/). The name of the container is set to one of our variables, and the type is always its inline-size (i.e., width in a horizontal writing mode).

The container-type property can only be applied to grid containers — not grid items. This means we’re unable to combine it with the grid-template-rows: subgrid value, which is why we needed to write a more complex selector to exclude those instances.

Demo

Check out the following demo to see how everything comes together.

See the Pen Grid system playground [forked] by utilitybend.

The demo is pulling in styles from another pen that contains the full CSS for everything we made together in this article. So, if you were to replace the .fluid-flex classname from the parent container in the HTML with another one of the layout utilities, the layout will update accordingly, allowing you to compare them.

Those classes are the following:

  • .repeating-grid,
  • .repeating-flex,
  • .fluid-grid,
  • .fluid-flex.

And, of course, you have the option of turning any grid items into grid containers using the optional .subgrid-rows class in combination with the .repeating-grid and .fluid-grid utilities.

Conclusion: Write Once And Repurpose

This was quite a journey, wasn’t it? It might seem like a lot of information, but we made something that we only need to write once and can use practically anywhere we need a certain type of layout using modern CSS approaches. I strongly believe these utilities can not only help you in a bunch of your work but also cut any reliance on CSS frameworks that you may be using simply for its layout configurations.

This is a combination of many techniques I’ve seen, one of them being a presentation Stephanie Eckles gave at CSS Day 2023. I love it when people handcraft modern CSS solutions for things we used to work around. Stephanie’s demonstration was clean from the start, which is refreshing as so many other areas of web development are becoming ever more complex.

After learning a bunch from CSS Day 2023, I played with Subgrid on my own and published different ideas from my experiments. That’s all it took for me to realize how extensible modern CSS layout approaches are and inspired me to create a set of utilities I could rely on, perhaps for a long time.

By no means am I trying to convince you or anyone else that these utilities are perfect and should be used everywhere or even that they’re better than <framework-du-jour>. One thing that I do know for certain is that by experimenting with the ideas we covered in this article, you will get a solid feel of how CSS is capable of making layout work much more convenient and robust than ever.

Create something out of this, and share it in the comments if you’re willing — I’m looking forward to seeing some fresh ideas!

The Difference Between Taxonomies, Categories, and Tags (Oh My!)

Category Image 052

A common question for new WordPress users is, “what’s the difference between categories and tags?” Like everyone knows what a “category” is, but the idea of “tags” can seem very similar. And then you throw in related WordPress concepts like “taxonomy”, and things can get confusing very quickly. But no worries, it’s really not that complicated. Let’s break it down..

Contents

Taxonomies

In WordPress, Taxonomies are used to organize posts. There are different types of taxonomies. The two most familiar types of Taxonomies are Categories and Tags. Both are enabled by default when you install WordPress. So when you create a post, you can choose which categories and tags should be assigned.

Currently, WordPress provides three taxonomies by default:

  • Categories – hierarchical taxonomy
  • Tags – non-hierarchical taxonomy
  • Post Formats – non-hierarchical taxonomy

In addition to these default taxonomies, a WordPress site also may support some Custom Taxonomies that are provided by plugins. For example, an e-commerce plugin may add custom taxonomies for things like “Product Type”, “Price Range”, “Brand Name”, or any other attribute. And for each of these taxonomies, you can add any number of terms.

Note: You can learn more about Post Formats at WordPress.org.

Notice in the above list of default taxonomies, that Categories are hierarchical while Tags are not. This means that categories can have sub-categories (aka child categories), like this:

  • Hats
  • Shirts
  • Pants
  • Shoes
    • Fast shoes
    • Slow shoes
    • Nice shoes
      • Smooth shoes
      • Fancy shoes
      • Funny shoes

Categories can have as many sub-categories as needed. Tags on the other hand, are non-hierarchical, so there are no child tags or grandchild tags. It’s a “flat” taxonomy. Further, any custom taxonomies may be either hierarchical or non-hierarchical, depending on how they are configured.

Note: Some themes also provide their own custom taxonomies, although they shouldn’t. According to WordPress best practices, adding custom taxonomies is “plugin territory”. Only plugins should provide custom taxonomies.

Simple example

To illustrate, say we have a post that describes a store product, like shoes. It might have the following taxonomies (left column) and terms (right column):

Post = Shoes that don't leave any footprints

	Category:      Store
	Tags:          stealth, speed
	Product Type:  shoes
	Price Range:   $100-$300
	Brand Name:    Rolf Ahl

This shows how taxonomies are used to define relationships between posts. So on the front end, visitors can sort items based on their category, tags, product type, and so forth. Indeed, any Aspect of your posts can be classified and organized with taxonomies.

Real-world example

To check out an effective use of taxonomies, visit Amazon.com and do a search for something like “shoes”. Then look in the sidebar at all the different ways to sort the results. Each of those sidebar sections (like “Shoe Size” and “Shoe Width”) are added via custom taxonomies. Amazon doesn’t actually run on WordPress, but it’s a great example of taxonomies.

Search results for 'shoe' at Amazon.comAll the sidebar options are examples of custom taxonomies.

As shown here, taxonomies enable your visitors to easily sort through your posts and find related and similar content.

Categories vs. Tags

As discussed, both Categories and Tags are types of Taxonomies. The only technical difference is that Categories are hierarchical, while Tags are not. So with categories, you can create sub-categories (or child categories). With tags, you cannot. Tags always have a “flat” organizational structure.

Other than that, the main difference between Categories and Tags has to do with scope. With WordPress:

  • Categories are used to broadly organize posts into groups
  • Tags are used to denote any specific post characteristics

I know that’s a bit abstract, so let’s go through some “real-world” examples..

Categories: real-world example

Let’s say it’s our job to clean up a house that has tons of junk in it. There are piles of stuff all over the place, and it’s our job to go in there and clean it all up. First we create two piles: “stuff that stays”, and “stuff that goes”. Those two piles represent categories.

After hauling away the “stuff that goes” pile, it’s time to organize the “stuff that stays”. Again, we use categories to make things easier. There are many ways we could categorize all the remaining items. We could organize by room, so our categories would be like:

  • Living Room
  • Kitchen
  • Bathroom
  • Bedroom

Makes sense, right? It’s the same idea with WordPress posts. Categories simply group similar types of posts together. For the purpose of organizing content and making it easier for visitors to find.

Categories: another example

Generally categories represent broad similarities among items, but you can get as specific as you’d like. For example, it’s common for a web-development site to group posts into the following categories:

  • CSS
  • HTML
  • PHP
  • JavaScript
  • Etc.

..such that each coding language gets its own category. That’s gonna keep posts broadly organized based just on the language. All posts about CSS go into the “CSS” category. All posts about HTML into the “HTML” category, and so forth.

But you can get more specific with categories. Say our tutorial site has a LOT of posts on all the coding languages. We might want to refine our categories to include version information, for example:

  • CSS
    • CSS 1.0
    • CSS 2.0
    • CSS 3.0
  • HTML
    • HTML 4.0
    • HTML 5.0
  • Etc.

Because categories can be hierarchical, we can get as specific or as broad as is necessary to organize your posts. And to organize things even further, we can throw tags into the mix..

Tags: real-world example

Returning to our “hoarder house” example, let’s look at how we can use tags to help further organize things. Recall that all the stuff currently is organized by room. So our categories are:

  • Living Room
  • Kitchen
  • Bathroom
  • Bedroom

In each room, we can further organize things by adding a tag to each item. For example, we tag the “chairs”, “tables”, “desks”, “electronics”, “clothes”, “food”, “towels”, and so on. And the nice thing about tags is that they can be added across categories. There may be “chairs” in both Living Room and Kitchen categories. Or there may be “electronics” in all categories. So when visitors arrive at your house, they can click the “food” tag and eat all of your food, regardless of which room it’s in :)

10-second summary

The difference between Taxonomies, Categories, and Tags:

  • Taxonomies are used to organize posts. WordPress provides two default Taxonomies: Categories and Tags. It’s also possible to create Custom Taxonomies. Taxonomies may be hierarchical or non-hierarchical.
  • Categories are used to broadly organize posts into groups. Categories may have a hierarchical structure.
  • Tags denote any specific post characteristics. Tags are non-hierarchical, flat organizational structure.

Resources


Chris’ Corner: Esoteric Stuff in CSS

Category Image 052

Listen I ain’t trying to scare you, but this CSS stuff can get complicated. It doesn’t have to be. CSS is just selectors with key value pairs in the end. The vast majority of CSS I write is pretty darn straightforward, especially once you have a general system (what files go where? how do we generally name things? how do we do variables?). But fair is fair, CSS can get wildly complex. It doesn’t help the complexity situation that anything new added increases that complexity, because, well, everything in CSS affects everything else. Selectors can get confusing and nesting can exacerbate that. Variables can get changed at any time and it’s not always clear from where. The situation on the page (sizing, events, settings) can effect what’s happening in CSS in increasingly bigger ways (querying containers, querying user preferences). If you want to push the edges of what CSS can do, now is the time.

I often save links of other people’s explorations of these edges of CSS. They are fascinating to me, naturally, as one of the proprietors of a front-end coding tool and ex-owner of CSS-Tricks. But sometimes I struggle to find a way to share them and contextualize them because of the complexity. In fact I think it’s fair to not use techniques based on complexity alone, after all, you write it you maintain it.

But let’s remove the limiter and look at CSS stuff regardless of how complex it might be.


I’ll start with one that has broken my brain for a few years now. @James0x57 calls this technique “Space Toggles” (who credits Ana Tudor for the discovery). Lea Verou calls it The -​-var: ; hack. Just to lock in my own understanding, I called it The CSS Custom Property Toggle Trick.

The idea is that CSS custom properties can be valid and invalid, a valid value even just being " " (a single space). You can concatenate that custom property with others to produce either-valid-or-invalid other custom properties. If it’s valid, you can do one thing, if it’s invalid, you can use the fallback for the custom property to do another thing. So it’s essentially if/then logic for custom properties.

The closest I ever came to simplifying it is this. And I admit it’s not exactly straightforward.

The good news is that CSS just decided that if() would be a thing, so now we wait for browser implementations. It should be quite a bit more straightforward, although the ease-of-use will lead to more exotic usage of it and, I’m afraid to admit, more complex CSS.


Have you ever prepped for needing to do a sorting algorithm in a job interview? Can you explain what a Bubble Sort is? It’s the one where you loop through a list comparing the two things next to each other, and swap them if they need to be swapped. You keep running through the list until you don’t do any more swaps. I think, anyway, I’m not some computer genius over here. GrahamTheDev is though! Their article Bubble Sort…in PURE CSS? is bonkers.

It literally works.

This is the complexity that comes through the ability to compare variables (e.g. we have min() and max() in CSS now) and set new variables based on other variables. Write enough of that with delays and animations and you got yourself a bubble sort. Good luck grokking all that though.

And speaking of the edges of CSS:

warning: on mobile the last few animations might not play and just go blank. On PC your fan may spin up!

This is a limitation of using so many calculations that rely on previous calculations…I am not sure if it runs out of memory or what, but I defo pushed the limits of CSS here!


What’s the value of cos(25deg) in CSS? Tyler Gaw wanted to figure it out exactly.

I know that will return a number between -1 and 1. But what number?

You can’t even set any property to exactly that, because just the number it produces is invalid for most properties.

You can do something like width: calc(1px * cos(25deg)) then check the width value in the devtools computed styles panel and get close, but not exact. Also, width: cos(25deg) is invalid CSS and using a custom prop like --v: cos(25deg) doesn’t really work either because the custom prop value is stored as cos(25deg).

But obviously cos(25deg) produces a number?! Tyler found a way to extract the CSS-generated number in JavaScript. I felt like having a poke at it too, but I didn’t get much further. I did discover that the output is a unitless number, so it’s valid for CSS properties that take unitless numbers, like line-height. So you can set line-height directly with it and then read the computed value. The problem is the computed value isn’t the direct output of the cos() function it’s the final px value so… blech, hard.


There is some CSS trickery that involves @keyframe animations. For example, styles applied during an animation apply extra strongly, so a style applied with a animation that runs for, say, a year is a way to do style overrides. Not recommended, heh. Setting animations to a particular place and pausing them is another weird trick for managing state in CSS.

Those, at least, I feel like I can get my brain around quickly. Animations have some extra power (and complexity) lately via Scroll-Driven Animations. Roman Komarov is the master recently of extremely exotic and complex CSS trickery, and his Scroll-Driven State Transfer is the pièce de résistance.

… an ability to mirror a particular state of some element — for example, hovered or focused — to an element in a different place on the page without a common or unique ancestral element that could have been used to deliver that state

You might think of :has() as the new hotness for being able to access state anywhere in CSS from anywhere else, and you’d be right, but apparently this trick is a bit more adaptable, not requiring us to write more CSS later:

… we could implement this with the :has() selector, but for any new values we’d have to modify the stylesheet afterwards

It looks like the trick involves those Space Toggles too, meaning I think this is one of the most complicated CSS tricks I’ve ever seen. Apart from the super math-y stuff that always blows my mind, that is.


We’ve established that animations can be one of the vehicles for CSS complexity, which is true when using them just to animate, not strong-arm them into some wild state machine.

One way animations can get complicated is combining them. It was just the other day I reminded myself that nesting elements and then animating them both essentially doubles the speed of the inside animation. That’s just shooting a cannon from an airplane though, no fancy tech there. CSS actually allows us to manually combine animations, with tools like animation-composition. It can be confusing though! Bramus wrote up The mysterious case of using CSS animation-composition: accumulate on a scale transform outlining just how weird it can get even in relatively simple situations. Maybe you’ll scratch your head too:

Accumulating a scale(0.5) with scale(2) does not give scale(2.5) but scale(1.5)

After scratching my own head about this long enough, it did sort of start to make sense. Even though blur(2) and blur(3) certainly make blur(5) when accumulated, those are both “blur something more”. In the case of scale, 0.5 makes something smaller. So adding 2.0 + 0.5 isn’t 2.5 because they aren’t both “do something more”, one is “make smaller” and one is “make bigger”, hence the spec having to step in and explain.

Chris’ Corner: Buttons, Modes, and a Couple of Layout Situations That Are Still a Bit Tricky

Category Image 052

If you ever need some inspiration for buttons, definitely check out Lucas Bonomi’s buttons.cool. This is a better-than-it-needs-to-be one-off site just for beautiful buttons:

But it’s not just a design gallery, it’s made for front-end developers in that you can see the code, see them being live-rendered right on the page, and of course, the best part is you can pop right over to CodePen for a look.

Looks like it’s taking submissions.


How hard is a Dark Mode to pull off? Or perhaps more accurately, how hard is it to pull off a second color mode? Some of us have dark-mode-first websites, ya know.

I thought Wes Bos phrased the question well:

Question for those who have implemented light/dark mode: how much is just swapping out variables, and how much is custom code, and tending to edge cases?

I answered: fiddy fiddy.

In the new version of CodePen we’re working on, we will have a site-wide theme setting (which is separated from what syntax highlighting theme you choose). CodePen being a pretty complex site, it involved quite a bit of CSS custom property setting. So in a sense, it was mostly just “swapping out variables”, but quite a few of those variables exist just because of different color modes, most of which I might even call an “edge case”. For us: north of 100 south of 200. I found this to be challenging but ultimately a fair approach.

Sometimes you see ideas going around of how simple it could be. For instance, he’s Akhil Arjun saying it can be done in one line:

html[theme='dark-mode'] {
    filter: invert(1) hue-rotate(180deg);
}

And here’s Mads Stoumann with a totally different 3-line approach:

body {
  background-color: Canvas;
  color: CanvasText;
  color-scheme: light dark;
}

While I appreciate a good CSS trick and these are good things to know about, I’m going to go ahead and say these super minimal approaches probably aren’t going to get you very far. You’re going to want better control than this and you’re going to need to deal with those edge cases.


Now that we have such powerful layout tools in CSS (keep ’em coming, CSS!) — it’s fun to see little layout situations that look fairly simple but are still a little challenging. Tyler Sticka ran across one he calls Tricky Floating Image Alignment. The idea is to have some text that is center aligned with an image, but if the text grows larger than the image, use the behavior of float.

I liked the solution in the end. It’s a throwback to the way we used to be able to vertically center stuff with top: 50%; transform: translateY(-50%). This will do the centering nicely, but when the text is bigger than the container, they essentially cancel out and so essentially do nothing.


Here’s another tricky layout situation, this time involving newfangled HTML and CSS features, namely anchor positioning. (Think of it as positioning an element based on another arbitrary element’s position.) Eric Meyer blogged it as Nuclear Anchored Sidenotes.

Imagine a footnote, except on a large enough screen, it’s more like a sidenote. That is, the note goes into empty sidebar space at the exact line that the footnote marker appears on. But to really pull this off, you’re using anchor positions of multiple elements:

Yes, I’m anchoring the sidenotes with respect to two completely different anchors, one of which is a descendant of the other.  That’s okay!  You can do that!

I did not know you could do that, but I like it.

top: anchor(top); /* implicit anchor */
left: anchor(--main right); /* named anchor e.g. anchor-name: --main; */

I only just heard of the CSS round() function the other day. It takes a value and rounds it. Ha.

line-height: round(2.2, 1); /* 2 */

I was blogging it with a number of other CSS functions I’d never heard of. Try this demo in Firefox to see a pretty clear example of why it could be cool. Of course Dan Wilson is all over it with a much more comprehensive look in The New CSS Math: round(). Dan looks closely at the syntax, sharing how you pass in not just a value, but the interval by which you want to do the rounding. Then optionally, even a “rounding strategy” if it’s important to you how that is done.

I feel like this falls into the category of “interesting layout related thing that would have been hard or impossible before but now isn’t.” Or at least “we’d probably have to do this in JavaScript before but it actually makes more sense in CSS.”


Looks like we’re going to get scrollbar-color and scrollbar-width across all browsers for real now. That’s the “real spec version” of doing this, instead of the more-capable (get gone-wild) WebKit styles of old. I wish it was more capable, but I’ll take standards over that any day.


While I’m still on this kick of “difficult CSS layout things”, you gotta see this Pen from Alex Riviere that handles this curved grid.

What’s striking to me about this is how… not weird it looks. It’s like if you were standing in a glass elevator going down and looking at these blocks, that’s just how they would look. But in order to pull that off while scrolling, some relatively exotic transform action needs to happen on them, which even involves new trigonometric functions in CSS (along with a scroll-timeline, which you can see has a fairly simply polyfill in this case).

Go take a peek at that CSS. The transforms are just a few lines, but wow that’s fancy.

Resizing Images On-The-Fly

Category Image 052

As a web architect, one of the many issues is asset management. And the most significant issue in assets is images. A naive approach would be to set an image and let the browser resize the image via CSS:

CSS
 
img {
    height: 100%;
    width: 100%;
    object-fit: contain;
}


Chris’ Corner: Swinging For It

Category Image 052

New year, new local code editor? It’s maybe worth a peak at Zed, at least. They do a good job in the one-sentence pitch:

Zed is a high-performance, multiplayer code editor from the creators of Atom and Tree-sitter.

All tech things have to be fast, so check. No shade either, speed is vital in all things tech, especially something you use heavily all day. Their main competition is clearly VS Code, which already gets some flack for slowness (feels fast to me 🤷), so leaning into a comparison that shows them some 4x faster on startup is sensible marketing.

“Multiplayer”… eh. I’m skepitcal about how much teams really care about this. VS Code did a whole “live share” thing a while back and I don’t think it struck much of a chord. I’m not against it as a feature, it’s just more like table stakes these days rather than a killer feature.

The last one… “from the creates of Atom and Tree-sitter” is a great pitch. People loved Atom. People are not happy Atom went away, so you get those people right out of the gate. Even if you didn’t use it, I think a lot of people respected it. Then Tree-sitter is this best-of-breed code parsing tool that all sorts of stuff uses (the new version of CodePen that will be out this year uses it heavily).

Will I actually switch? No idea. I’m always down to try new things. But I’ve written about this before, and I have my own criteria on switching code editors. For me, the new one needs to be able to behave essentially like the old one. If anything is too obnoxious, I’ll just switch back. If I can switch without terrible annoyances, then I’m happy to explore changes and different features and such.

And to keep me (and I think this is generally true, not just for me) it needs killer features. Maybe that is speed, but I don’t think the competition in this area is slow enough for that to be the big thing.

Maybe the AI stuff will be one of the killer features. AI is such a big thing these days, but VS Code has Github Copilot, which is great and a huge competitive advantage. Except… Zed supports GitHub Copilot! Nice move. And check out the video where they’ve integrated GPT-4 into the editor, and you invoke it by highlighting a block of text and typing a prompt. Very classy, I think.

It appears as if they are really making a swing for it with Zed and that’s good for everyone. Making a business out of it is going to be tricky too. Looks like they already have a team of 10. I can tell you that 10 world-class developers aren’t cheap. It doesn’t look like Zed is open source yet, so best guess is the plan is to make it paid. That’s tough in a world where VS Code is free (although Copilot is not). Panic makes it work with Nova though, so it’s not uncharted territory. I think developers are happy to throw bucks at tools that are even a little bit better, so I would bet on Zed doing pretty decently, myself. The good design of their landing page makes me feel like they have their heads screwed on straight.

Gotta love companies making a big swing on things. I feel like that’s what Arc has been doing since the beginning with their new web browser. They are constantly shipping and taking risks on big features. And it has all the hallmarks of big swings: some big hits, some big misses. I think Arc has massive potential as being the best web browser out there, but it seems like that’s not where they are headed. In a vague end-of-year where-we’re-headed video, they say they actually want to build a whole new computer. That seems like a wildly different task and set of skills needed, but hey, a big swing is a big swing. They are kind of “pre-money” so I guess it’s more of a pivot.

I feel like another company that is trying to make a swing for it in a crowded market this year is Bun. A brand new JavaScript runtime in a totally different language is a big endeavor. Competition in this space feels warranted and good for everyone. And also like the business model is just as nebulous as all the other companies mentioned here. There was some pretty pointed pushback about Bun, which both feels fair and like that’s exactly what you’d expect when you’re doing something new and bold.

How to Display Any Number of Posts in a WordPress Loop

Category Image 052

Do you want to show multiple blog posts in a WordPress loop?

Using the loop, WordPress processes each of the posts to be displayed on the current page. It formats them according to how they match specified criteria within the loop tags.

In this article, we will show how to display any number of posts in a WordPress loop.

How to display any number of posts in a WordPress loop

What Is the WordPress Loop?

The loop is used by WordPress to display each of your posts. It is PHP code that’s used in a WordPress theme to show a list of posts on a web page. It is an important part of WordPress code and is at the core of most queries.

In a WordPress loop, there are different functions that run to display posts. However, developers can customize how each post is shown in the loop by changing the template tags.

For example, the base tags in a loop will show the title, date, and content of the post in a loop. You can add custom tags and display additional information like the category, excerpt, custom fields, author name, and more.

The WordPress loop also lets you control the number of blog posts that you show on each page. This can be helpful when designing an author’s template, as you can control the number of posts displayed in each loop.

That being said, let’s see how to add any number of posts to a WordPress loop.

Adding Any Number of Posts in a WordPress Loop

Normally, you can set the number of posts to be displayed in the loop from your WordPress admin panel.

Simply head to Settings » Reading from the WordPress dashboard. By default, WordPress will show 10 posts.

Reading settings WordPress

However, you can override that number by using a Super Loop, which will allow you to display any number of posts in that specific WordPress loop.

This will allow you to customize the display settings of your pages, including author profiles, sidebars, and more.

First, you will need to open a template file where you would like to place the posts and then simply add this loop:

<?php
// if everything is in place and ready, let's start the loop
if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>

	// to display 'n' number of posts, we need to execute the loop 'n' number of times
	// so we define a numerical variable called '$count' and set its value to zero
	// with each iteration of the loop, the value of '$count' will increase by one
	// after the value of '$count' reaches the specified number, the loop will stop
	// *USER: change the 'n' to the number of posts that you would like to display

	<?php static $count = 0;
	if ( $count == "n" ) {
		break;
	} else { ?>

		// for CSS styling and layout purposes, we wrap the post content in a div
		// we then display the entire post content via the 'the_content()' function
		// *USER: change to '<?php the_excerpt(); ?>' to display post excerpts instead

		<div class="post">
			<?php the_title(); ?>
			<?php the_content(); ?>
		</div>

		// here, we continue with the limiting of the number of displayed posts
		// each iteration of the loop increases the value of '$count' by one
		// the final two lines complete the loop and close the if statement

		<?php $count ++;
	} ?>
<?php endwhile; ?>
<?php endif; ?>

Note: You will need to replace the value of ‘n‘ in the if ( $count == "n" ) part of the code and choose any number.

An easy way to add this code to your WordPress website is by using the WPCode plugin. It is the best code snippet plugin for WordPress that helps you manage custom code.

By using WPCode, you don’t have manually edit theme template files and risk breaking something. The plugin will automatically insert the code for you.

First, you need to install and activate the free WPCode plugin. For more details, please see our guide on how to install a WordPress plugin.

Upon activation, you can head to Code Snippets » + Add Snippet from your WordPress dashboard. Next, you need to select the ‘Add Your Custom Code (New Snippet)’ option.

Add new snippet

After that, simply paste the custom code for the WordPress loop that we showed you above into the ‘Code Preview’ area.

You will also need to enter a name for your code and set the ‘Code Type’ to ‘PHP Snippet’.

Add custom loop code to WPCode

Next, you can scroll down to the ‘Insertion’ section and choose where you would like to run the code.

By default, WPCode will run it everywhere on your WordPress website. However, you can change the location to a specific page or use a shortcode to insert the code.

Edit insertion method for code

For this tutorial, we will use the default ‘Auto Insert’ method.

When you are done, don’t forget to click the toggle at the top to make the code ‘Active’ and then click the ‘Save’ button. WPCode will now deploy the code on your WordPress blog and display the specified number of posts in the WordPress loop.

We hope this article helped you learn how to display any number of posts in a WordPress loop. You may also want to see our guide on how to exclude sticky posts from the loop in WordPress and our expert picks for the must-have WordPress plugins for business websites.

If you liked this article, then please subscribe to our YouTube Channel for WordPress video tutorials. You can also find us on Twitter and Facebook.

The post How to Display Any Number of Posts in a WordPress Loop first appeared on WPBeginner.

Solving Media Object Float Issues With CSS Block Formatting Contexts

Category Image 052

Let’s imagine we’re making a small component. It can be anything, really, but let’s use a media object as an example. Nicole Sullivan had a solid definition of media objects from way back in 2010, and you probably already know the pattern well: some form of media (often an image) on the left and text beside it on the right. The media could be an image or a video, for example.

This is the basic HTML for the layout, minimized for brevity:

<section class="container">
  <article class="float-left">
    <img src="https://picsum.photos/100">
      <p>I've never had to cook or clean since I discovered Xyz. They perform all my tasks for me. I recommend them.</p>
      <h3>Dan Somore</h3>
  </article>

  <!-- more articles -->

</section>

This HTML gives us a <section> element that is the container for four <article> elements, where each one is a testimonial container that holds an <img> and a <div> with a block of text — our media objects.

Let’s apply some light styling in CSS:

/* Give the parent container breathing room */
.container {
  padding: 20px;
}

/* 
  Styles for each testimonial container 
  Each container is floated left
*/
.float-left {
  border: 2px solid blue;
  background-color: transparent;
  float: left;
  width: 45%;
  min-height: 150px;
  margin-bottom: 20px;
  margin-right: 20px;
}

/* Testimonial images are floated left */
img {
  float: left;
  margin-right: 10px;
}

This code is by no means perfect. In fact, it introduces the wrapping and overflow issues we’re about to discuss. We will look at these issues together before getting into solutions.

Issue 1: Height Collapsing

When an element is floated in its container, it exits its normal document flow and into a floated position, making no contributions to the container’s height. In a container of many floated media objects, the container element’s height is collapsed to contain only non-floated elements. The collapsed height might be inconspicuous in containers without a border or non-floated elements and could disrupt the layout of other elements after a media object container. However, this issue can be easily discovered if there is a non-floated element in the container, among other floated elements.

Let’s add a border to the parent container to see the height-collapsing effect.

The height of the content is what influences the height of the testimonial container. If the image were in the container’s flow, it would be taller than the text, and the container would adjust to it. But, alas, that’s not the case since we introduced a block formatting context when floating the image.

The popular solution with a single line of CSS on the testimonial’s parent container:


.container {
  overflow: auto;
}

The BFC this generates establishes a new document flow within the page’s root element, containing all the container's child elements, including floated media objects. It effectively prevents the testimonial elements from being displaced beyond the parent container’s borders — no extra divs or pseudo-elements are needed like the clearfix approach.

See the Pen Float Solutions: overflow: auto [forked] by Geoff Graham.

That certainly gets the job done! But I want to show you one more way to do this because I believe it’s the best of the bunch.

The Best Solution: display: flow-root

display: flow-root was introduced to address inconsistencies associated with using overflow for generating BFCs. In fact, display: flow-root was explicitly designed to produce BFC, while the overflow property is designed to manage content that surpasses its container. Consequently, overflow can induce unintended side effects, from unwanted scrollbars to data loss.

That’s why I recommend using display: flow-root. It is meant to create a BFC when you need it, whereas the other solutions are more like workarounds.

Conclusion

CSS block formatting contexts are great because they allow you to leave the main document flow, allowing elements to interact differently in a layout. But, of course, those different interactions can feel like buggy behavior if you’re unaware that you’re actually working in a different formatting context.

This is exactly why we have modern layout techniques like Flexbox and Grid. Before we had them, floats were a nice trick for faking columns. But the BFC they created wasn’t so nice. Hence clever workarounds like the clearfix to create a BFC to wrangle the other BFC.

Perhaps the bigger takeaway from all this, though, is to evaluate your layout strategy. If you’re reaching for a float, is it really the best option for what you’re trying to do? Because if so, you may as well embrace the natural text-wrapping behavior rather than trying to fight it. And if you don’t want to fight it, that’s a sure sign you ought to reach for a more modern layout technique, like Flexbox or Grid.

Resources

Further Reading On SmashingMag

Chris’ Corner: Design Shrinking

Category Image 052

While I don’t think you should publish to Medium (at least not as the only place you publish something, you should write on your own site that you control), I get why other people do. You quickly sign up, write some words, hit publish, and the result is a pretty clean-looking presentation of your writing. Not to mention familiar to the general public. Medium is big and popular enough that people have seen it and are comfortable with it. I mean Barack Obama writes there so goes a long way in terms of endorsement.

It’s that clean comfortable design that I think it’s especially notable (when it’s not being covered up by a mysteriously activated paywall). So it’s interesting to see their designers write about the effort that goes into that look. Breana Jones says they re-focused on the single-column look:

We’re bringing back the single-column page layout and removing the two-column layout across all stories on desktop.

You can still find recommended stories from Medium and author bios, but these sections will now be below the story, instead of right next it. This allows readers to focus on the story without any distractions on the side.

I applaud that, really. The single column look really works great on the web for primarily written content and it’s harder than it looks to pull off, especially at a huge company with lots of business objectives fighting for space on that screen.

Design does tend to be associated with cleanliness. Like a “clean” design is a “good” design, generally, especially when we’re talking product design for wide varied audiences. I like how Matt Birchler says:

If you are sitting next to someone at a computer and you know how to use the thing and they don’t, it’s very easy for you to say, click here, do this. When you click this, this is what’s going to happen. It’s very easy to do that. The goal of a good user interface is to give someone that experience without you having to be in the room with them.

That’s as good of an explanation for digital product design as I’ve heard. I caveated it with “digital product” because design is a pretty broad discipline. Designing a wooden bookshelf is a pretty different endeavor with different constraints and goals. Wood has a grain that the designers will work with. The web, too, has a grain. Amelia Wattenberger says:

In the digital world, especially on the web, we’re used to things being stacked vertically. Scrolling, scrolling, through boxes of content, one… on top… of another.

Things are always arranged linearly — top-to-bottom. Or, if we’re feeling spicy, left-to-right.

This is all great for neat, orderly content. But what about when thoughts are complex, unsorted, exploratory?

This is her introduction to thinking about infinite canvases, which is a little against the grain on the web, but absolutely doable and sometimes quite useful. Consider how you can drag and zoom a Figma canvas anywhere without any constrained edges at all. But this approach isn’t just for design, it can be useful for things like thinking through problems with teams, doing organizing and grouping.

I love me some good “general rules” for design concepts. There is so much nuance and it depends situations in design and development, when there is some just do this advice I appreciate it. I think of things like how headers always have less line-height than body text, things should align with other things, and you should probably double the white space.

CodePen’s own Rachel Smith has some excellent general advice in this vein that I didn’t really understand until now:

If you’re moving an object from out of the frame/stage in to the frame/stage, use an ease-out variation.

If you’re moving an object from inside the frame to outside the frame, use an ease-in variation.

If you’re moving an object from one place to another in the frame, use an ease-in-out variation.

I can remember that!


Lemme leave you with a little one: Magick.css. It’s one of those “just link it up and your semantic basic classless HTML will look nice. It’s got a pretty fancy look to it with some unusual font choices, but it might be your bag. My favorite in this genre is still new.css.

Chris Corner: Unusual Ideas with Great Results

Category Image 052

SVG Short Circuiting

SVG is normally a pretty efficient file format. If an image is vector in nature, leaving it as vector is normally a good plan as it will like scale well and look pretty darn crips. But of course, It Depends. Super complex vector graphics can get huge, and a raster (i.e. JPG, PNG, etc) version can actually be smaller. This can happen with little tiny images too where the straight up low amount of pixels is just pretty efficient.

This should be the kind of thing computers are good at, right? You’re in luck if you’re using Eleventy. Zach wrote about a thing the Image component can do for Eleventy called SVG Short Circuiting. The idea is, if your source image is SVG, it can make raster versions to help with efficiency. But if the SVG version ends up smaller than any of the other produced versions, it will discard the raster versions.

A nice looking font that helps dyslexia

Worth knowing:

According to the International Dyslexia Association, as much as 15 to 20 percent of the U.S. population may have symptoms of dyslexia. Those include slow or inaccurate reading, weak spelling, and poor writing.

Jill Stakke

Also worth knowing: these people, and really probably anybody can be helped along with better typefaces. That is, typefaces designed in such a way that the are less confusing and less problematic for people with dyslexia.

I’ve seen Dyslexie before, which is pretty neat. But to be frank, it does look a smidge childish which might make it a tough choice when a brand voice needs to be more serious looking. A crappy trade-off, but such is life.

I’ve just seen Oliva King’s Inclusive Sans which, to my eyes, it extremely nice looking and covers the general criteria laied out by Sophie Beier in Designing for Legibility.

  1. Clear distinction between I, l and 1
  2. Non-mirroring of letters d, b, q and p
  3. Distinction between O and 0
  4. Wider, more open counter forms on c, o, a and e
  5. A higher x-height for easier readability at small sizes
  6. Wider default letter-spacing
  7. Clear difference between capital height and ascender height

Just look at how #2 is handled:

Super classy if you ask me. I wanna use it for something. I’m stoked at how good it looks at body copy sizes.

An HTML element as a mask

The vast majority of masks are either shapes in black/white such that they hide or reveal what is behind them in that shape exactly. Or a gradient, such that they fade out what is behind them little by little.

Artur Bień has another idea of what a mask can be: any HTML element. You can set up a simple-but-clever SVG filter to filter out all black.

I gave it a quick shot myself just to have a play and it worked great.


Now that you’re primed into thinking of layering things on top of each other and doing exotic filtering to get weird and cool results, you’re ready for this next one.

Javier Bórquez: Motion extraction with mostly CSS.

Say you wanted to look at a video where only the things that are moving are visible, and the rest is essentially blacked out. Why? I don’t know don’t think about that part too hard. Maybe it’s a way to spot changes in security video easier. Or more likely it’s just a really cool final effect.

You’d think getting that done would involve sophisticated video processing technology. But nope: CSS. The trick is so perfect:

One video is placed on top of the other, playing slightly ahead. Then, by styling the top video with mix-blend-mode: difference in CSS, we make is so only the pixels that have changed between the two frames are shown.

So cool. That’s my favorite trick I’ve seen in a while.

Single Element Gradient Borders

Actually I have another trick that is right in the zone with the last two that is also just extremely cool. You gotta admit the gradient border look is pretty hot right now.

There are number of ways to pull that off, but they typically involve multiple stacked elements and decently involved trickery or limitations. The above is just one element, and it’s showcasing how you also aren’t limited with what you want to do in the body of the element (there using a backdrop-blur).

Ben Frain documents a trick he found in the freeCodeCamp forums. You slap a pseudo element on the main element to create the border, and then essentially knock out a hole in the middle.

Here is the clever bit I have never seen before; we then use a mask, and a mask composite. This allows us to create a ‘shape’, that our gradient border will inhabit. To create this shape, we need to composite two images together and find the difference. That might sound like a lot of work but we can make those two images with CSS using a linear-gradient. It doesn’t matter that the linear-gradient is actually just a flat white colour, the fact that it is defined as a linear-gradient means that the browser renders the outcome of that notation as an image and the image can be composited. So the first mask is a linear gradient set to the padding-box, which then crucially does not include the border, and the second gradient is the full size, and the difference between them is the border shape. Genius!!!!

Genius indeed.

Chris’ Corner: Things I Like

Category Image 052

I like Melanie Sumner’s coining of the phrase Continuous Accessibility. To me, it’s like a play on the term Continuous Integration (CI) that is very pervasive. We build CI pipelines to lint our code, test our code, and test our code primarily, but all sorts of things can be done. We can test new code for performance regressions for example. So too could and should we be testing our new code for accessibility issues. Continuously, as it were. I’m very guilty of failing at the continuous part. I care about and act on accessibility issues, but I tend to do it in waves or sprints rather than all the time.


I like the career value that Ben Nadel assigns to learning RegEx. He says not a day goes by he doesn’t use them in some form (!). I wouldn’t say that’s true for me, but certainly every week or two I need to think about them, and over the years, my fear-factor in using them has scaled down to zero. They really aren’t that bad, it’s just a long steady learning curve to the point where eventually you feel like even if I’m slow I can ultimately reason this out. Either figuring out an existing one or writing a new one. Ben doesn’t just talk about it abstractly, he lists loads of practical examples.

Before I move on, allow me to show you Hillel Wayne agreeing with Regexes are Cool and Good (that’s my kind of title). Hillel mentions some valid reasons why people have a distaste for them, but then brings up a super good point: RegExes are particularly good when you’ve got some muscle memory for them and use them in little one-off use cases.

… where regex really shines is in interactive use. When you’re trying to substitute in a single file you have open, or grep a folder, things like that. Readability doesn’t matter because you’re writing a one-off throwaway, and fragility is fine because you’re a human-in-the-loop. If anything goes wrong you will see that and tweak the regex.

Heck yeah. If you get good at it, using them for Find/Replace reasons in your code editor can make you look like damn superhero.

Oh and thank heavens for RegEx101 and sites like it. So good.


I really like the CSS only “scroll-to-top” trick that David Darnes created and Stefan Judis wrote up. It’s just so deliciously clever. A scroll-to-top link is just a UX convenience and accessibility feature, as it not only scrolls to the top but moves focus back up there as well. It’s like…

<a href="#top" class="back-to-top-link">Back to Top</a>

But where and when do you show it? It could just be down in the footer of a site. But a classy way to do it is to show it on long-scrolling pages pretty much all the time — just not when the page is already scrolled to the top. Say you want to wait until the user has scrolled down at least 200px or something like that. Feels like JavaScript territory, but no, that’s where David’s trick shines: this can all be done in CSS.

The bare-bones part of the trick:

.back-to-top-link {
  margin-block-start: calc(100vh + 200px);
  position: sticky;
  bottom: 1rem;
  left: 1rem;
}

Here’s a demo.


I like the relative color syntax. Support for it is coming along and it’s in Interop 2024 so “actually using it” isn’t terribly far away. What I like is that it allows you to manipulate a color on the fly in a way that will actually work well without needing anything other than native CSS.

Thought process:

  • I’ve got this orange color
  • I wish I had a version of it that was a bit darker
  • … and is a bit alpha transparent.

So I’ve got the color:

body {
  --color: #f06d06;
}

Then I can use it, and I can use my modified version easily.

.box {
  background: var(--color);
  border: 20px solid oklch(from var(--color) calc(l - 0.5) c h / 0.5);
}

I’m using OKLCH there because it has “perceptually uniform lightness” so if I manipulate all my colors the same amount, they will feel the same amount manipulated. I don’t have to use that function, I could use rgb() or hsl() or even the generic color(). That’s the thing with the relative color syntax, it’s not any particular function, it’s largely that from keyword.


I like the idea of things challenging the dominance of npm. Much like Deno is challenging Node, and is literally from the same creator, now vlt is challenging npm and is from the same creator. Well, he’s on the team anyway. I remember listening to Darcy Clarke on Syntax saying some smart stuff about this new package manager possibility. Like, I’m the user, right? It’s my computer, and I’m asking this tool to go get a package for me. Why can’t I say “don’t get the README though, I don’t need it, and definitely skip the 1.5 MB JPG in that README, I just need the JavaScript file.” Makes a lot of sense to me. Give me a pre-built version! Don’t give me the types, I’m not using TypeScript. That kind of thing. I’m sure that like 1% of what this thing will be able to do, I just like the fresh thinking. I’m sure it’s more about the security. We’ve got JSR in there shaking stuff up now too, which I like because it isn’t friggin lowecase.

Chris’ Corner: Hard Things

Category Image 052

Julia Evans has an extremely relatable and extremely charming talk in Making Hard Things Easy. Julia has a way of putting her finger on technology concepts that are notoriously difficult and making them easier to understand. She does this both by sharing her own tactics, like learning a reduced set of options or commands, as well as by producing very approachable guides.

I like her formula: infrequent use + lots of gotchas = disaster.

(As a CSS guy who regularly hears people complain about CSS, this tracks.)

Another trick to avoiding that disaster is… using computers! Tools like linters can help you fix (or avoid) the very mistakes that can make a technology frustrating or error prone. She uses the tool ShellCheck, which I’d never heard of, as an example to avoiding problems in Bash scripts. Then, sharing when you find tools like this that actually help you. I found that last bit especially interesting. It’s good to be “intellectually honest” about sharing tools that really have helped you, not tools that seem like they could help you, because they look nice or whatever.


Speaking of hard things… you know what can be hard? Refactoring. I’ve probably over-repeated this, but David Khorshid one said “It should be called legendary code not legacy code”, referring to the idea that code that is in production doing work, even if you think it might be sloppy, inefficient, inelegant, is literally doing the job it needs to do. Whereas some theoretically rewritten wonderful code has yet to prove itself.

Miroslav Nikolov writes:

Code refactoring may cost a fortune if not done right. A dysfunctional revamped system or new features coupled with incorrect rewrite is, with no doubt, damaging. One can argue to what extent.

Refactoring code can be very dangerous, so it’s worth being very considerate about what you’re doing. A few of Miroslav’s points:

✅ Isolate improvements from features. Do not apply them simultaneously.

❌ Do not mix expensive cleanups with other changes. But do that for small improvements.


This makes me think about TypeScript.

TypeScript is (uh, obviously) newer than JavaScript, so there is a good amount of code out there that has been refatored into TypeScript. Whether than was worth it or not is up for debate. People that love it might say that a refactor like this actually makes the code safer, and they probably aren’t wrong to some degree, although it wouldn’t be hard to argue that any refactored code has risks.

There is also cost to the TypeScript itself. Build tooling and whatnot of course, but also the syntax itself. Remy Sharp has made the call that his own personal code isn’t in TypeScript, partially for this reason:

A “well crafted” definition, type or interface (still no idea when I should use each), is often a huge cognitive load on me.

Being presented with lots of double colons, <T> when I’m not sure what T refers to, a wall of interfaces and more is an upfront cost on me, the reader.

Often the types will be tucked away in other files (probably good) but working out the argument required to a function call often leaves me distracted in the task of understanding what’s required rather than making my function call.

I feel that. I’m slowly getting better at TypeScript myself, because at CodePen we’ve decided to take advantage of it when we can. I can see the value in it fairly regularly, but I’m also fairly regularly frustrated by it and question the hours lost. I’ve felt this way for years, and I’m still not quite sure what to make of that.


One of the reasons you might be refactoring something is because you’ve decided on some new abstractions. A classic, in my experience, is that you’re adding, dropping, or changing a framework. The old one just isn’t doing it anymore, times have changed, and you either want to go vanilla or move to something more modern. There is probably some kind of axiom where any sufficiently large codebase is always undergoing at least one refactoring per hundred thousand lines of code or the like.

Have you read the Hammer Factories thing? It’s a pretty satisfying read, save for a few dated stabs at comedy that read pretty misogynisticly. Sometimes you just need a hammer, is the thing, it’s clearly the right tool for the job, but the industry wants you to you some all-in-one hammer, wait, no, a hammer factory, wait, no, a factory for building hammer factories, wait, no…


It feels true to me that front-end specific work has always been treated as lower-value than back-end work. Don’t hate me, but part of me feels like that’s fair. I’m a front-end guy myself and actually think it’s extremely valuable, but ultimately most products real value lies in some kind of unique back-end magic. The problems on the back-end, on the whole, are harder and riskier and scarier, and that translates to higher paying roles. Of course there is tons of nuance here. A product with a very decent back end and total garbage front end is likely to have problems catching and may outright fail because of a poor experience for the people actually using the thing, and making an experience people love is weighted toward the front end. Or as Josh Collinsworth recently wrote:

In many ways, CSS has greater impact than any other language on a user’s experience, which often directly influences success. Why, then, is its role so belittled?

There used to be a time where if you knew both front end and back end you were a unicorn and it was considered very rare and you were a powerful force in this industry. Now unicorns are dead. We call that “full stack” now and it’s all but expected that you are one. Especially if you’re skilled in the front end, you can’t just say that, you have to say “full stack” or your job prospects ain’t looking great. Then the actual expectations of full stack mean that you’re good at the JavaScript stuff, you’re fine with the work that connects that JavaScript client work with JavaScript on the server, and you know enough front end to use a design system, library, or hack some workable things together.

It’s just a thought, anyway. It solidified in my mind reading Andrew Walpole:

The full-stack developer was borneth!

It looks great on paper, especially to the payroll department: One person to fill traditionally two roles. But in reality, we know it doesn’t work that way. It may be a role for a technology generalist to thrive in, but one person’s effort is finite, and consistent, quality development across the entire product development spectrum requires focus and expertise. Nevertheless, start-ups soaked up the efficiency, and in a tumultuous churn of web tech it was a decent defense.


There is a new Node.js website and it’s always fun to read a little behind-the-scenes. That would be a hard job but it looks like they did a great job.

How to Add Custom Meta Boxes in WordPress Posts and Post Types

Featured Imgs 13

Do you want to learn how to create custom meta boxes for your WordPress posts, pages, and custom post types?

WordPress adds metadata to your content automatically, such as the publication date, categories, and tags. However, you may also want to add your own custom meta data.

In this article, we will show you how to easily add unique information to your content, by creating a custom meta data box in WordPress.

How to add custom meta boxes in WordPress posts and post types

What is a Custom Meta Box in WordPress?

When you create posts and pages, or custom post types in WordPress, that content usually has its own metadata. This metadata is information related to the content like date and time, the author name, title, and more.

You can also add your own metadata using the default custom fields box.

Adding custom meta boxes in WordPress posts

Pro Tip: Can’t see the Custom Fields box in the post editor? Then see our guide on how to fix custom fields not showing in WordPress.

The Custom Fields box is a good solution if you just want to add custom metadata to a few posts. However, if you plan to add lots of unique information to your content, then it makes sense to create a custom metadata box.

In fact, many of the popular WordPress plugins add custom meta boxes to the Edit screen for posts and pages. In the following image, you can see how easy it is to add SEO information to your post, using a custom meta box provided by AIOSEO.

The All in One SEO (AIOSEO) WordPress plugin

With that being said, let’s see how you can easily add custom meta boxes in WordPress posts and post types.

How to Add Custom Meta Boxes in WordPress Posts and Post Types

The easiest way to add custom meta boxes to WordPress is by using Advanced Custom Fields. This plugin allows you to attach all kinds of extra information to your posts and pages, and then show that data to visitors using a shortcode.

The first thing you need to do is install and activate the Advanced Custom Fields plugin. For more details, see our step-by-step guide on how to install a WordPress plugin.

Create a Custom Meta Box

Upon activation, go to ACF » Field Groups and then click on the ‘Add New’ button.

Adding a custom field to your WordPress website

Here, you can create the custom fields that will appear in the metadata box.

To start, you’ll need to type a title into the field that shows ‘Field Group Title’ by default. This will appear in the WordPress content editor, and it will be used as the title of your meta box.

With that being said, you should use something descriptive, especially if you manage a multi-author WordPress blog or share the dashboard with other people.

How to easily add custom meta data to your website or blog

With that done, you’re ready to add the first field to your meta box.

Add Custom Fields to the Meta Box

To start, open the ‘Field Type’ dropdown and choose the type of field you want to add, such as Text, Date Picker, Checkbox, or any other field type.

Adding custom fields to the WordPress content editor

After that, type in a label for the field.

Advanced Custom Fields will show this label before the field, so it will help users understand what information they need to enter.

The Advanced Custom Fields WordPress plugin

Advanced Custom Fields will generate the ‘Field Name’ automatically, so you can leave this field empty.

With that done, you may want to type in a ‘Default Value.’ This will be added to the page, post, or custom post type automatically if the user doesn’t add their own information.

Adding default values to custom WordPress fields

You may see more options depending on the kind of field you’re creating. For example, if you selected ‘Image’ from the ‘File Type’ dropdown, then you can choose the image format.

Most of these options are self-explanatory so you can follow the onscreen instructions to configure the custom field.

When you’re happy with how the field is set up, click on ‘Close Field’ to collapse the section.

Adding custom data to a website or blog

You can now add more fields to the custom meta box by clicking on the ‘Add Field’ button.

Then, simply configure the field by following the exact same process described above.

Saving a custom field group

Add a Custom Meta Box to the WordPress Content Editor

When you’re happy with how the custom meta box is set up, you’ll need to define where and when the meta box will appear.

Scroll to the ‘Settings’ section and then click on the ‘Location Rules’ tab.

Controlling where custom content appears in the WordPress content editor

Advanced Custom Fields can add the box to all kinds of content. For example, you can show the meta box on specific post types, categories, taxonomies, navigation menus, and more.

Simply use the dropdown menus to choose where the meta box will appear in your WordPress dashboard. For example, if you accept guest posts then you may want to add the box to all posts in the ‘Guest Posts’ category.

Creating content rules using a WordPress plugin

After that, click on the ‘Presentation’ tab.

Here, you can choose the meta box style, where it appears on your WordPress blog, and where the label and instructions will appear.

ACF's presentation settings in the WordPress dashboard

If you plan to add multiple boxes in the same location, then you can change the order they appear in by typing into the ‘Order No’ field.

For example, showing the most important meta boxes towards the top of the screen may improve your editorial workflow.

If you’re unsure, then you can leave this field set to 0.

Reorganizing fields in the WordPress content editor

On this screen, you’ll also see a list of all the fields that WordPress usually shows on the post edit screen.

If you want to hide a field, then simply check its box. For example, if you’re using custom fields to create an author info box, then you may want to hide the default ‘Author’ field.

Hiding fields in the WordPress post editor

When you’re happy with the changes you’ve made, click on ‘Save Changes’ to make the field group live.

You’ve now successfully created a custom meta box for your WordPress post, page, or custom post type. Depending on your settings, you can now visit the post editor to see the custom meta box in action.

An example of a custom meta data box, created using a free WordPress plugin

Displaying Your Custom Meta Box Data in WordPress Theme

You’ve now successfully added a custom meta box to the WordPress dashboard. Any information users type into the meta box will be stored in the WordPress database when they save or publish the post. However, this information won’t appear on your website by default.

With that in mind, let’s make sure the custom metadata appears in your WordPress theme, so visitors can see it.

You can do this using shortcode or by editing your WordPress theme files.

How to Display Custom Metadata using Shortcode

Adding a shortcode in WordPress is the easiest method, and allows you to control exactly where the information appears on your website. For example, if you’ve created a ‘Star Rating’ field, then you can show this information after the post title, inside the content, in the footer, or anywhere else simply by adding a shortcode.

However, you will need to add a shortcode to every page, post, or custom post type manually. This can take a lot of time and effort, especially if you have a lot of content.

To get a field’s shortcode, go to ACF » Field Groups. Then, hover over the field group that you want to display and click on the ‘Edit’ link when it appears.

Editing a meta data field group

You’ll now see all the fields that make up this group.

For each field you want to display, make a note of the value in the ‘Name’ field.

How to show custom data in your WordPress theme using shortcode

With that done, go to the page, post, or custom post type where you want to show the custom metadata.

You can now click on the ‘+’ icon and type in ‘Shortcode.’

Adding shortcode to a WordPress page or post

When the right block appears, click to add it to your layout.

You can now add the following shortcode to the block, making sure to replace "article_byline" with the name of the field you want to show.

Adding custom meta data to a WordPress theme

You can now repeat these steps to add multiple custom fields to the post.

When you’re happy with the changes you’ve made, either click on the ‘Publish’ or ‘Update’ button. Now, simply visit your WordPress website to see the custom metadata in action.

An example of custom meta data, displayed using a shortcode

How to Display Custom Metadata by Editing Your WordPress Theme

If you want to show custom metadata in the same location on every page, post, or custom post type, then you can add code to your WordPress theme files.

This can save you time in the long-term, but it isn’t the most beginner-friendly method. You’ll also lose all the custom code the next time you update your WordPress theme, which is why we recommend creating a child theme. You can then add your custom code to the child.

If you haven’t edited your theme files before, then take a look at our beginner’s guide on how to copy and paste code in WordPress.

You’ll need to edit the file where you want to show the custom metadata. This will vary depending on your theme, but you’ll usually need to edit your site’s single.php, content.php, or page.php file.

Once you have the right file, you’ll need to add the code inside the WordPress loop. To find this loop, simply search for code that looks something like this:

	<?php while ( have_posts() ) : the_post(); ?>

You can then paste your code after this line and before the line that ends the loop:

	<?php endwhile; // end of the loop. ?>

As an example, your custom field code should look something like this:

	<h2 class="article-byline"><?php the_field('article_byline'); ?></h2>

Notice how we wrapped the code in a h2 heading with a CSS class. This allows us to format and style the custom field later by adding custom CSS to our theme.

Here’s another example:

<blockquote class="article-pullquote">
 
<?php the_field('article_pullquote'); ?>
 
</blockquote> 

When adding code to your theme, don’t forget to replace the field names.

With that done, you can visit any post where you’ve already entered data into the custom fields. You will now see your unique metadata in action.

How to add custom fields to a WordPress theme

We hope this article helped you learn how to add custom meta boxes in WordPress posts and post types. You may also want to see our guide on how to create automated workflows in WordPress, or see our expert pick of the best SEO plugins and tools that you should use.

If you liked this article, then please subscribe to our YouTube Channel for WordPress video tutorials. You can also find us on Twitter and Facebook.

The post How to Add Custom Meta Boxes in WordPress Posts and Post Types first appeared on WPBeginner.

Chris’ Corner: Some AdviCSS

Category Image 052

Get it?! Like “advice”, but for CSS.

When should you nest CSS?

Scott Vandehey says:

There’s a simple answer and a slightly more complicated answer. The simple answer is “avoid nesting.” The more practical, but also more complex answer is “nest pseudo-selectors, parent modifiers, media queries, and selectors that don’t work without nesting.”

The big idea behind avoiding nesting (which is a native CSS feature now, if you hadn’t heard) is that it can lead to specificity increases that just aren’t necessary. Like:

.card {
  .content {
    .byline {

    }
  }
}

That .byline selector probably doesn’t gain anything by being nested like that. Break it out of there and it’ll be more re-usable and easier to override if you need to.

But this:

.card {
  @container (width > 60ch) {

  }
}

Is probably good! It just saves you from having to re-write the .card selector again. Scott gets more in-depth though with more examples and I largely agree.

How do you adjust an existing color light and darker?

I’m a biiiig fan of the relative color syntax, which is great at this job, but before I go on a tangent about that, it’s not well supported yet so let’s not. It’s on the Interop 2024 list though!

Better supported is color-mix(), and Cory LaViska has the story on using it for this job:

Using color-mix(), we can adjust the tint/shade based on the background color, meaning we don’t need to manually select lighter/darker colors for those states. And because we’re using OKLCH, the variations will be perceptually uniform, unlike HSL.

By mixing white and black into colors, and doing it in the OKLCH color space, we can essentially tint and shade the colors and know that we’re doing it evenly across any color we have. This is as opposed to the days when a lot of us tried to use darken() and such in Sass only to find extremely different results across colors.

How are the final values of Custom Properties calculated?

Stephanie Eckles:

Custom properties – aka “CSS variables” – seem fairly straightforward. However, there are some behaviors to be aware of regarding how the browser computes the final values. A misunderstanding of this process may lead to an unexpected or missing value and difficulty troubleshooting and resolving the issue.

Custom Properties follow the cascade and are computed at runtime, for one thing, which is the whole reason that they cannot be preprocessed ahead of time. But it’s more complex than that. What if the value is valid for a custom property (most anything is), but not valid for the way you are trying to use it?

This is a real head scratcher:

html { color: red; }

p { color: blue; }

.card { --color: #notacolor; }

.card p { color: var(--color); }

Turns out .card p will actually be red (I would have guessed blue), but Stephanie explains:

The .card p will be the inherited color value of red as provided by the body. It is unable to use the cascaded value of blue due to the browser discarding that as a possible value candidate at “parse time” when it is only evaluating syntax.

How do you accommodate people who struggle with transparent interfaces?

Adam Argyle explains it can be like this, using this media query you may or may not have heard of:

.example {
  --opacity: .5;

  background: hsl(200 100% 50% / var(--opacity));

  @media (prefers-reduced-transparency: reduce) {
    --opacity: .95;
  }
}

Adam had lots of practical examples in the post, and does consider that word reduced, and how it doesn’t mean absolutely none ever.

What units should you use for spacing properties?

Me, I just use rem usually as that’s what I use for nearly everything else. But Ashlee M Boyer argues that while stuff like text makes good sense to use relative units, spacing need not scale at that same rate:

When a user is customizing their viewing experience, they thing that’s most important to them and their task at hand is the content. Spacing isn’t often vital for a user to perform their task, so it doesn’t need to grow or scale at the same rate as the content itself.

When spacing between content grows, it eats up vital real estate and becomes harder to manage.

Ashlee proves it with a before video and an after video, after being moving relative units to absolute units for spacing.

How do you make every Sass file automatically include common imports?

This one hits home for me, as someone with a codebase with easily hundreds of Sass files that all start with something like @import "@codepen/variables"; Wouldn’t it be cool if Sass could just assume we wanted to do that for every file?

Austin Gil covered this a while back on doing it with Vite. When you define your Vite config, you can like:

  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `@import "@/assets/_shared.scss";`
      }
    }
  }

I see webpack can do it too, but I’m not sure if Sass alone can be configured to do it, although I wish it could.