Adding Fluid Typography Support to WordPress Block Themes

Fluid typography is a fancy way of “describing font properties, such as size or line height, that scale fluidly according to the size of the viewport”. It’s also known by other names, like responsive typography, flexible type, fluid type, viewport sized typography, fluid typography, and even responsive display text.

Here is an example of fluid typography that you can play live (courtesy of MDN documentation). CSS-Tricks has covered fluid typography extensively as well. But the point here is not to introduce you to fluid typography, but how to use it. More specifically, I want to show you how to implement fluid typography in WordPress 6.1 which recently introduced a fluid type feature directly in the WordPress Block Editor.

Open up your style.css file, slap in a style rule with fancy clamp()-ing on the font-size property, and good to go, right? Sure, that’ll give you fluid text, but to get Block Editor controls that make it possible to apply fluid type anywhere on your WordPress site? That requires a different approach in these block-ified days.

Fluid typography support in Gutenberg

Some WordPress theme developers have been using the clamp() function to define a fluid font-size, in their WordPress themes, even in newer “block” themes such as Twenty Twenty-Two, Twenty Twenty-Three, and others.

But the Gutenberg plugin — the one that contains experimental development for WordPress Block and Site Editor features — introduced support for fluid typography starting in version 13.8. That opened the door for implementing at a theme level so that fluid type can be applied to specific elements and blocks directly in the Block Editor. CSS-Tricks was even given a shout-out in the Pull Request that merged the feature.

That work became part of WordPress Core in WordPress 6.1. Rich Tabor, one of the earlier advocates of fluid typography in the Block Editor says:

[Fluid typography] is also a part of making WordPress more powerful, while not more complicated (which we all know is quite the challenge). […] Fluid typography just works. Actually, I think it works great.

This Make WordPress post highlights the approach taken to support the feature at the block level so that a fluid font size is applied to blocks dynamically by default. There are some benefits to this, of course:

  • It provides a way for theme authors to activate fluid typography without worrying about implementing it in code.
  • It applies fluid typography to specific typographical entities, such as elements or blocks in a maintainable and reusable way.
  • It allows flexibility in terms of font size units (e.g. px, rem, em, and %).

Now that this new feature is available in the WordPress Block Editor by default, theme authors can apply uniform fluid typography without writing additional code.

Blocks that support typography and spacing settings

Gutenberg 14.1 released on September 16, 2022, and introduced typographic settings on a bunch of blocks. That means the text settings for those blocks were set in CSS before and had to be changed in CSS as well. But those blocks now provide font and spacing controls in the Block Editor interface.

Illustrated list of WordPress blocks that received font and spacing controls in the Gutenberg plugin. There are 31 total blocks.

That work is currently slated to be added to WordPress 6.1, as detailed in this Make WordPress blog post. And with it is an expanded number of blocks that with typography support.

Illustrated list of 60 WordPress blocks gaining typography and font size support in WordPress 6.1.
WordPress blocks that will support typography settings in the upcoming WordPress 6.1 release.

Declaring fluid type in a WordPress block theme

So, how do we put this new fluid typography to use in WordPress? The answer is in theme.json, a new-ish file specific to block themes that contains a bunch of theme configurations in key:value pairs.

Let’s look at a rule for a large font in theme.json where contentSize: 768px and we’re working with a widesize: 1600px layout. This is how we can specify a CSS font-size using the clamp() function:

"settings": {
  "appearanceTools": true,
  "layout": {
    "contentSize": "768px",
    "wideSize": "1600px"
  },
  "typography": {
    "fontSizes": [ 
      {
        "name": "Large",
        "size": "clamp(2.25rem, 6vw, 3rem)",
        "slug": "large"
      }
    ]
  }
}

As of WordPress 6.1, only rem, em and px units are supported.

That’s great and works, but with the new fluid type feature we would actually use a different approach. First, we opt into fluid typography on settings.typography, which has a new fluid property:

"settings": {
  "typography": {
    "fluid": true
  }
}

Then we specify our settings.fontSizes like before, but with a new fluidSize property where we can set the min and max size values for our fluid type range.

"settings": {
  "appearanceTools": true,
  "layout": {
    "contentSize": "768px",
    "wideSize": "1600px"
  },
  "typography": {
    "fontSizes": [ 
      {
        "size": "2.25rem",
        "fluidSize": {
          "min": "2.25rem",
          "max": "3rem"
        },
        "slug": "large",
        "name": "Large"
      }
    ]
  }
}

That’s really it. We just added fluid type to a font size called “Large” with a range that starts at 2.25rem and scales up to 3rem. Now, we can apply the “Large” font to any block with font settings.

How does this works under the hood? Rich Tabor offers a nice explanation, as does this Pull Request in GitHub. In short, WordPress converts the theme.json properties into the following CSS rule:

.has-large-font-size {
  font-size: clamp(36px, calc(2.25rem + ((1vw - 7.68px) * 1.4423)), 48px);
}

…which is applied to the element, say a Paragraph Block:

<p class="has-large-font-size">...</p>

Initially, I found it hard to understand and wrap around in my mind the concept of the CSS clamp() function without also learning about the min(), max(), and calc() functions. This calculator tool helped me quite a bit, especially for determining which values to use in my own theme projects.

For demonstration purposes, let’s use the calculator to define our font-size range so that the size is 36px at a 768px viewport width and 48px at a 1600px viewport width.

Entering values into the online calculator for fluid typography.

The calculator automatically generates the following CSS:

/* 36px @ 768px increasing to 48px @ 1600px */
font-size: clamp(36px, calc(2.25rem + ((1vw - 7.68px) * 1.4423)), 48px);

The calculator provide options to select input units as px, rem, and em. If we select rem unit, the calculator generates the following clamp() value:

/* 2.25rem @ 48rem increasing to 3rem @ 100rem */
font-size: clamp(2.25rem, calc(2.25rem + ((1vw - 0.48rem) * 1.4423)), 3rem);

So, those minimum and maximum values correspond to the the fluidSize.min and fluidSize.max values in theme.json. The min value is applied at viewports that are 768px wide and below. Then the font-size scales up as the viewport width grows. If the viewport is wider than 1600px, the max is applied and the font-size is capped there.

Examples

There are detailed testing instructions in the merged Pull Request that introduced the feature. There are even more testing instructions from Justin Tadlock’s pre-prelease post on Make WordPress.

Example 1: Setting a new fluid font setting

Let’s start with Justin’s set of instructions. I used in a modified version of the default Twenty Twenty-Three theme that is currently under development.

First, let’s make sure we’re running the Gutenberg plugin (13.8 and up) or WordPress 6.1, then opt into fluid type on the settings.typography.fluid property in the theme.json file:

{
  "version": 2,
  "settings": {
    "appearanceTools": true,
    "layout": {
      "contentSize": "768px",
      "wideSize": "1600px"
    },
    "typography": {
      "fluid": true
    }
  }
}

Now, let’s drop the settings.typography.fontSizes examples in there:

{
  "version": 2,
  "settings": {
    "appearanceTools": true,
    "layout": {
      "contentSize": "768px",
      "wideSize": "1600px"
    },
    "typography": {
      "fluid": true
      "fontSizes": [
        {
          "name": "Normal",
          "size": "1.125rem",
          "fluid": {
            "min": "1rem",
            "max": "1.5rem"
          },
          "slug": "normal"
        }
      ]
    }
  }
}

If everything is working correctly, we can now head into the WordPress Block Editor and apply the “Normal” font setting to our block:

The WordPress Block Editor interface showing a paragraph block and the fluid typography settings for it.

Nice! And if we save and inspect that element on the front end, this is the markup:

Inspecting the WordPress Paragraph block in DevTools.

Very good. Now let’s make sure the CSS is actually there:

DevTools showing the font-size custom property for the WordPress Paragraph block's fluid typography.

Good, good. Let’s expose that CSS custom property to see if it’s really clampin’ things:

Revealing the custom property value in DevTools, showing a CSS clamp function.

Looks like everything is working just as we want it! Let’s look at another example…

Example 2: Excluding a font setting from fluid type

This time, let’s follow the instructions from the merged Pull Request with a nod to this example by Carolina Nymark that shows how we can disable fluid type on a specific font setting.

I used the empty theme as advised in the instructions and opened up the theme.json file for testing. First, we opt into fluid type exactly as we did before:

{
  "version": 2,
  "settings": {
    "appearanceTools": true,
    "layout": {
      "contentSize": "768px",
      "wideSize": "1000px"
    },
    "typography": {
      "fluid": true
    }
  }
}

This time, we’re working with smaller wideSize value of 1000px instead of 1600px. This should allow us to see fluid type working in an exact range.

OK, on to defining some custom font sizes under settings.typography.fontSizes:

{
  "version": 2,
  "settings": {
    "typography": {
      "fluid": true,
      "fontSizes": [
        {
          "size": ".875rem",
          "fluid": {
            "min": "0.875rem",
            "max": "1rem"
        },
          "slug": "small",
          "name": "Small"
        },
        {
          "size": "1rem",
          "fluid": {
            "min": "1rem",
            "max": "1.5rem"
          },
          "slug": "normal",
          "name": "Normal"
        },
        {
          "size": "1.5rem",
          "fluid": {
            "min": "1.5rem",
            "max": "2rem"
          },
          "slug": "large",
          "name": "Large"
        },
        {
          "size": "2.25rem",
          "fluid": false,
          "slug": "x-large",
          "name": "Extra large"
        }
      ]
    }
  }
}

Notice that we’ve applied the fluid type feature only on the “Normal”, “Medium”, and “Large” font settings. “Extra Large” is the odd one out where the fluid object is set to false.

the WordPress Block Editor interface with four Paragraph blocks, each at a different font size setting.

What WordPress does from here — via the Gutenberg style engine — is apply the properties we set into CSS clamp() functions for each font size setting that has opted into fluid type and a single size value for the Extra Large setting:

--wp--preset--font-size--small: clamp(0.875rem, 0.875rem + ((1vw - 0.48rem) * 0.24), 1rem);
--wp--preset--font-size--medium: clamp(1rem, 1rem + ((1vw - 0.48rem) * 0.962), 1.5rem);
--wp--preset--font-size--large: clamp(1.5rem, 1.5rem + ((1vw - 0.48rem) * 0.962), 2rem);
--wp--preset--font-size--x-large: 2.25rem;

Let’s check the markup on the front end:

Inspecting the WordPress Paragraph blocks in DevTools.

Good start! Let’s confirm that the .has-x-large-font-size class is excluded from fluid type:

Showing the font-size custom property for the Extra Large font setting in DevTools.

If we expose the --wp--preset--font-size--x-large variable, we’ll see it’s set to 2.25rem.

Revealing the Extra Large font size custom property value, showing 2.25rem.

That’s exactly what we want!

Block themes that support fluid typography

Many WordPress themes already make use of the clamp() function for fluid type in both block and classic themes. A good example of fluid typography use is the recently released Twenty Twenty-Three default theme.

I’ve reviewed all the block themes from WordPress Block Theme directory, examining theme.json file of each theme and to see just how many block themes currently support fluid typography — not the new feature since it’s still in the Gutenberg plugin as of this writing — using the CSS clamp() function. Of the 146 themes I reviewed, the majority of them used a clamp() function to define spacing. A little more than half of them used clamp() to define font sizes. The Alara theme is the only one to use clamp() for defining the layout container sizes.

Understandably, only a few recently released themes contain the new fluid typography feature. But here are the ones I found that define it in theme.json:

And if you read my previous post here on CSS-Tricks, the TT2 Gopher Blocks theme I used for the demo has also been updated to support the fluid typography feature.

Selected reactions to the WordPress fluid typography features

Having fluid typography in WordPress at the settings level is super exciting! I thought I’d share some thoughts from folks in the WordPress developer community who have commented on it.

Matias Ventura, the lead architect of the Gutenberg project:

Rich Tabor:

As one of the bigger efforts towards making publishing beautifully rich pages in WordPress, fluid typography is a pretty big experience win for both the folks building with WordPress — and those consuming the content.

Automattic developer Ramon Dodd commented in the Pull Request:

Contrast that idea with font sizes that respond to specific viewport sizes, such as those defined by media queries, but do nothing in between those sizes. theme.json already allows authors to insert their own fluid font size values. This won’t change, but this PR offers it to folks who don’t want to worry about the implementation details.

Nick Croft, author of GenesisWP:

Brian Garner, designer and principal developer advocate at WPEngine:

A few developers think some features should be an opt-in. Jason Crist of Automattic says:

I love the power of fluid typography, however I also don’t believe that it should just be enabled by default. It’s usage (and the details of it) are important design decisions that should be made carefully.

You can also find a bunch more comments in the official testing instructions for the feature.

Wrapping up

The fluid typography feature in WordPress is still in active development at the time of this writing. So, right now, theme authors should proceed to use it, but with caution and expect some possible changes before it is officially released. Justin cautions theme authors using this feature and suggests to keep eye on the following two GitHub issues:

There is also still lots of ongoing work on typography and other design-related WordPress tools. If you’re interested, watch this typography tracking GitHub ticket and design tools related GitHub issues.

Resources

I used the following articles when researching fluid type and how WordPress is implementing it as a feature.

Tutorials and opinions

CSS-Tricks


Adding Fluid Typography Support to WordPress Block Themes originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

Consistent, Fluidly Scaling Type and Spacing

When Chris first sent me this prompt, I was thinking about writing about progressive enhancement, but that subject is so wide-reaching to be one thing and all too predictable, especially for those already familiar with my writing. Saying that, what I’m going to outline in this article also isn’t just one thing either, but the day I meet a writing prompt exactly will be the day pigs start flying. This one group of things, though, will change how you write CSS.

I personally think this group of things lets a lot of sites down—especially in a responsive design sense. The things in this group are typography and spacing. So often, I see inconsistent spacing—especially vertically—that makes content hard to scan and creates this subtle, disjointed feeling. The same goes for type: huge headings on small viewports, or heading hierarchies that visually have no contrast in size, rendering them useless in a visual sense.

There is a pretty easy fix for all of this using a sizing scale and fluid type, and I promise it’ll make your websites look and feel heaps better. Let’s get into it.

What the heck is a sizing scale?

A sizing scale is a uniform progression of sizes based on a scale—or, more accurately, a ratio.

Screensjhot of the type-scale.com type scale tool. It displays eight variations of font sizes in black on a white background starting from largest to smallest vertically. To the left of the examples are options to configure the output, including base font size, type of scale, Google font selection, and preview text.

In that screenshot of type-scale.com, I’ve selected a “Perfect Fourth” scale which uses a ratio of 1.333. This means each time you go up a size, you multiply the current size by 1.333, and each time you go down a size, you divide by 1.333.

If you have a base font size of 16px, using this scale, the next size up is 16 * 1.333, which is 21.33px. The next size up is 21.33 * 1.333, which is 28.43px. This provides a lovely curve as you move up and down the scale.

CSS clamp() and type fluidity

For years, if you were to say, “Hey Andy, what’s your favorite CSS feature?” I would immediately say flexbox, but nah, not these days. I am a clamp() super fan. I wrote about it in more detail here, but the summary of clamp() is that it does clever stuff based on three parameters you give it:

  • a minimum value
  • an ideal value
  • a maximum value

This makes for a very useful tool in the context of fluid typography and spacing, because you write CSS like this:

.my-element {
  font-size: clamp(1rem, calc(1rem * 3vw), 2rem);
}

This tiny bit of CSS gives us full responsive text sizes based on the viewport width with handy locks to make sure sizes don’t get too big or too small.

It’s really important to test that your text is legible when you zoom in and zoom out when using clamp. It should be very obviously larger or smaller. Because we’re using a rem units as part of our fluid calculation, we’re helping that considerably.

Putting it all together

Right, so we’ve got a size scale and CSS clamp() all set up—how does it all come together? The smart people behind Utopia came up with the simplest, but handiest of approaches. I use their type tool and their spacing tool to create size scales for small and large viewports. Then, using clamp(), I generate a master size scale that’s completely fluid, as well as a Sass map that informs Gorko’s configuration.

$gorko-size-scale: (
  '300': clamp(0.7rem, 0.66rem + 0.2vw, 0.8rem),
  '400': clamp(0.88rem, 0.83rem + 0.24vw, 1rem),
  '500': clamp(1.09rem, 1rem + 0.47vw, 1.33rem),
  '600': clamp(1.37rem, 1.21rem + 0.8vw, 1.78rem),
  '700': clamp(1.71rem, 1.45rem + 1.29vw, 2.37rem),
  '800': clamp(2.14rem, 1.74rem + 1.99vw, 3.16rem),
  '900': clamp(2.67rem, 2.07rem + 3vw, 4.21rem),
  '1000': clamp(3.34rem, 2.45rem + 4.43vw, 5.61rem)
);

This snippet is from my site, piccalil.li, and the typography is super simple to work with because of it.

You could also translate that into good ol’ CSS Custom Properties:

:root {
  --size-300: clamp(0.7rem, 0.66rem + 0.2vw, 0.8rem);
  --size-400: clamp(0.88rem, 0.83rem + 0.24vw, 1rem);
  --size-500: clamp(1.09rem, 1rem + 0.47vw, 1.33rem);
  --size-600: clamp(1.37rem, 1.21rem + 0.8vw, 1.78rem);
  --size-700: clamp(1.71rem, 1.45rem + 1.29vw, 2.37rem);
  --size-800: clamp(2.14rem, 1.74rem + 1.99vw, 3.16rem);
  --size-900: clamp(2.67rem, 2.07rem + 3vw, 4.21rem);
  --size-1000: clamp(3.34rem, 2.45rem + 4.43vw, 5.61rem);
};

This approach also works for much larger sites, too. Take the new web.dev design or this fancy software agency’s site. The latter has a huge size scale for large viewports and a much smaller, more sensible, scale for smaller viewports, all perfectly applied and without media queries.

I’m all about keeping things simple. This approach combines a classic design practice—a sizing scale—and a modern CSS feature—clamp()—to make for much simpler CSS that achieves a lot.

How to Get a Pixel-Perfect, Linearly Scaled UI

Dynamically scaling CSS values based on the viewport width is hardly a new topic. You can find plenty of in-depth coverage right here on CSS-Tricks in articles like this one or this one.

Most of those examples, though, use relative CSS units and unitless values to achieve fluid scaling. That loses pixel perfection and usually introduces text wrapping and layout shifts once the screen goes below or above a certain threshold.

But what if we really do want pixel perfection? What if, let’s say, we are developing a complex real-time analytics dashboard to be viewed on large TVs at a conference room or as some PWA to be opened exclusively on mobile and tablet devices, as opposed to text-heavy blogs and news websites? Those are cases where we need more precision.

In other words, what if we want to scale designs uniformly? Of course, one can scale the content with CSS transforms based on the available width as covered in this article — this way, the correct ratios are preserved.

However, we can also achieve fluid proportional scaling UIs using pixel values in CSS. They scale appropriately based on the device screen real estate, all while preserving their pixel-perfect proportions. Further, we can still use pixel values and automatically convert them to relative CSS units if working in pixels is more comfortable or familiar.

Scaling our UI

Let’s try to implement this awesome dashboard, courtesy of Craftwork. We need to make it in such a way that it scales perfectly and preserves all the texts line counts, margins, image sizes, etc.

Let’s work in CSS pixel values and use SCSS for speed and convenience. So, if we are to target the title of one of these card widgets, our SCSS might look something like this:

.cardWidget {
  .cardHeading {
    font-size: 16px;
  }
}

Nothin’ fancy. Nothing we have not seen before. Being a pixel value, this will not scale.

This design was created with a container that’s 1600px wide. Let’s assume that at 1600px, the ideal font size for the titles of the cards should be 16px since that’s how it’s designed.

Now that we have the “ideal” container width font size for this width, let’s scale our CSS pixel values accordingly using the current* viewport width:

/*
  1600px is the ideal viewport width that the UI designers who
  created the dashboard used when designing their Figma artboards

  Please not we are not using pixel units here, treating it purely
  as a numeric value.
*/
--ideal-viewport-width: 1600;
/*
  The actual width of the user device
*/
--current-viewport-width: 100vw;

.cardWidget {
  .cardHeading {
    /*
      16px is the ideal font size that the UI designers want for
      1600px viewport width.

      Please note that we are not using pixel units here,
      treating it purely as a numeric value.
    */
    --ideal-font-size: 16;
    /*
      Calculate the actual font size:

      We take our idealFontSize and multiply it by the difference
      between the current viewport width and the ideal viewport width.
    */
    font-size: calc(
      var(--ideal-font-size) * (var(--current-viewport-width) / var(--ideal-viewport-width)
    );
  }
}

As you can see, we treat the ideal font size we obtained from the design as a base and multiply it by the difference between the current and ideal viewport widths. How does this look mathematically? Let’s say we are viewing this web app on a screen with the exact same width as the mockup:

--current-device-width: 100vw; // represents 1600px or full width of the screen
--ideal-viewport-width: 1600; // notice that the ideal and current width match
--ideal-font-size: 16;
// this evaluates to:
font-size: calc(16 * 1600px / 1600);
// same as:
font-size: calc(16 * 1px);
// final result:
font-size: 16px;

So, since our viewport width matches perfectly, our font-size ends being exactly 16px at the ideal viewport width of 1600px.

As another example, let’s say we are viewing the web app on a smaller laptop screen that’s 1366px wide. Here is the updated math:

font-size: calc(16 * 1366px / 1600);
// same as:
font-size: calc(16 * 0.85375px);
// final result:
font-size: 13.66px;

Or let’s say we are viewing this on a full high-definition display at 1920px wide:

font-size: calc(16 * 1920px / 1600);
// same as:
font-size: calc(16 * 1.2px);
// final result:
font-size: 19.2px;

You can see for yourself how even though we use pixel values as reference, we are actually able to proportionally scale our CSS values based on the difference in width between the ideal and current viewport sizes.

Here is a small demo I built to illustrate the technique:

Here’s a video for convienence:

Clamping the min and max viewport width

Using this current approach, the design scales to match the viewport size, no matter how big or small the viewport gets. We can prevent this with CSS clamp() which allows us to set a minimum width of 350px and maximum width of 3840px. This means that if we are to open the web app on a device with 5000px width, our layout will stay locked at 3840px:

--ideal-viewport-width: 1600;
--current-viewport-width: 100vw;
/*
  Set our minimum and maximum allowed layout widths:
*/
--min-viewport-width: 350px;
--max-viewport-width: 3840px;

.cardWidget {
  .cardHeading {
    --ideal-font-size: 16;
    font-size: calc(
      /*
        The clamp() function takes three comma separated expressions
        as its parameter, in the order of minimum value, preferred value
        and maximum value:
      */
      --clamped-viewport-width: clamp(var(--min-viewport-width), var(--current-viewport-width), var(--max-viewport-width);
      /*
        Use the clamped viewport width in our calculation
      */
      var(--ideal-font-size) * var(--clamped-viewport-width) / var(--ideal-viewport-width)
    );
  }
}

Let’s make a helper for the unit conversions

Our code is quite verbose. Let’s write a simple SCSS function that converts our values from pixels to relative units. That way, we can import and reuse anywhere this anywhere without so much duplication:

/*
  Declare a SCSS function that takes a value to be scaled and
  ideal viewport width:
*/
@function scaleValue(
  $value,
  $idealViewportWidth: 1600px,
  $min: 350px,
  $max: 3840px
) {
  @return calc(
    #{$value} * (clamp(#{$min}, 100vw, #{$max}) / #{$idealViewportWidth})
  );
}

/*
  We can then apply it on any numeric CSS value.

  Please note we are passing not pixel based, but numeric values:
*/
.myElement {
  width: #{scaleValue(500)};
  height: #{scaleValue(500)};
  box-shadow: #{scaleValue(2)} #{scaleValue(2)} rgba(black, 0.5);
  font-size: #{scaleValue(24)};
}

Porting this to Javascript

Sometimes CSS doesn’t cut it and we have to use JavaScript to size a component. Let’s say we are constructing an SVG dynamically and we need to size its width and height properties based on an ideal design width. Here is the JavaScript to make it happen:

/*
  Our helper method to scale a value based on the device width
*/
const scaleValue = (value, idealViewportWidth = 1600) => {
  return value * (window.innerWidth / idealViewportWidth)
}

/*
  Create a SVG element and set its width, height and viewbox properties
*/
const IDEAL_SVG_WIDTH = 512
const IDEAL_SVG_HEIGHT = 512

const svgEl = document.createElement('svg')
/* Scale the width and height */
svgEl.setAttribute('width', scaleValue(IDEAL_SVG_WIDTH))
svgEl.setAttribute('height', scaleValue(IDEAL_SVG_WIDTH))

/*
  We don't really need to scale the viewBox property because it will
  perfectly match the ratio of the scaled width and height
*/
svg.setAttribute('viewBox', `0 0 ${IDEAL_SVG_WIDTH} ${IDEAL_SVG_HEIGHT}`)

The drawbacks of this technique

This solution is not perfect. For example, one major drawback is that the the UIs are no longer zoomable. No matter how much the user zooms, the designs will stay locked as if they are viewed at 100% zoom.

That said, we can easily use traditional media queries, where we set different ideal numeric values at different viewport widths:

.myElement {
  width: #{scaleValue(500)};
  height: #{scaleValue(500)};
  box-shadow: #{scaleValue(2)} #{scaleValue(2)} rgba(black, 0.5);
  font-size: #{scaleValue(24)};
  @media (min-width: 64em) {
    width: #{scaleValue(800)};
    font-size: #{scaleValue(42)};
  }
}

Now we can benefit from both media queries and our pixel-perfect linear scaling.

Wrapping up

All of this is an alternative way to implement fluid UIs. We treat the pixel-perfect values as pure numeric values, and multiply them by the difference between the current viewport width and the “ideal” viewport width from the designs.

I have used this technique extensively in my own work and hope that you will find some use of it too.


The post How to Get a Pixel-Perfect, Linearly Scaled UI appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.

Working around the viewport-based fluid typography bug in Safari

Sara digs into a bug I happened to have mentioned back in 2012 where fluid type didn’t resize when the browser window resized. Back then, it affected Chrome 20 and Safari 6, but the bug still persists today in Safari when a calc() involves viewport units.

Sara credits Martin Auswöger for a super weird and clever trick using -webkit-marquee-increment: 0vw; (here’s the documentation) to force Safari into the correct behavior. I’ll make a screencast just to document it:

I randomly happened to have Safari Technology Preview open, which at the moment is Safari 15, and I see the bug is fixed. So I wouldn’t rush out the door to implement this.

Direct Link to ArticlePermalink


The post Working around the viewport-based fluid typography bug in Safari appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.

Linearly Scale font-size with CSS clamp() Based on the Viewport

Responsive typography has been tried in the past with a slew of methods such as media queries and CSS calc().

Here, we’re going to explore a different way to linearly scale text between a set of minimum and maximum sizes as the viewport’s width increases, with the intent of making its behavior at different screen sizes more predictable — All in a single line of CSS, thanks to clamp().

The CSS function clamp() is a heavy hitter. It’s useful for a variety of things, but it’s especially nice for typography. Here’s how it works. It takes three values: 

clamp(minimum, preferred, maximum);

The value it returns will be the preferred value, until that preferred value is lower than the minimum value (at which point the minimum value will be returned) or higher than the maximum value (at which point the maximum will be returned).

In this example, the preferred value is 50%. On the left 50% of the 400px viewport is 200px, which is less than the 300px minimum value that gets used instead. On the right, 50% of the 1400px viewport equals 700px, which is greater than the minimum value and lower than the 800px maximum value, so it equates to 700px.

Wouldn’t it just always be the preferred value then, assuming you aren’t being weird and set it between the minimum and maximum? Well, you’re rather expected to use a formula for the preferred value, like:

.banner {
  width: clamp(200px, 50% + 20px, 800px); /* Yes, you can do math inside clamp()! */
}

Say you want to set an element’s minimum font-size to 1rem when the viewport width is 360px or below, and set the maximum to 3.5rem when the viewport width is 840px or above. 

In other words:

1rem   = 360px and below
Scaled = 361px - 839px
3.5rem = 840px and above

Any viewport width between 361 and 839 pixels needs a font size linearly scaled between 1 and 3.5rem. That’s actually super easy with clamp()! For example, at a viewport width of 600 pixels, halfway between 360 and 840 pixels, we would get exactly the middle value between 1 and 3.5rem, which is 2.25rem.

Line chart with the vertical axis measured in font size rem unites from 0 to 4, and the horizontal axis measuring viewport width from 0 to 1,060 pixels. There are four blue points on the grid with a blue line connecting them.

What we are trying to achieve with clamp() is called linear interpolation: getting intermediate information between two data points.

Here are the four steps to do this:

Step 1

Pick your minimum and maximum font sizes, and your minimum and maximum viewport widths. In our example, that’s 1rem and 3.5rem for the font sizes, and 360px and 840px for the widths.

Step 2

Convert the widths to rem. Since 1rem on most browsers is 16px by default (more on that later), that’s what we’re going to use. So, now the minimum and maximum viewport widths will be 22.5rem and 52.5rem, respectively.

Step 3

Here, we’re gonna lean a bit to the math side. When paired together, the viewport widths and the font sizes make two points on an X and Y coordinate system, and those points make a line.

A two-dimensional coordinate chart with two points and a red line intersecting them.
(22.5, 1) and (52.5, 3.5)

We kinda need that line — or rather its slope and its intersection with the Y axis to be more specific. Here’s how to calculate that:

slope = (maxFontSize - minFontSize) / (maxWidth - minWidth)
yAxisIntersection = -minWidth * slope + minFontSize

That gives us a value of 0.0833 for the slope and -0.875 for the intersection at the Y axis.

Step 4

Now we build the clamp() function. The formula for the preferred value is:

preferredValue = yAxisIntersection[rem] + (slope * 100)[vw]

So the function ends up like this:

.header {
  font-size: clamp(1rem, -0.875rem + 8.333vw, 3.5rem);
}

You can visualize the result in the following demo:

Go ahead and play with it. As you can see, the font size stops growing when the viewport width is 840px and stops shrinking at 360px. Everything in between changes in linear fashion.

What if the user changes the root’s font size?

You may have noticed a little flaw with this whole approach: it only works as long as the root’s font size is the one you think it is — which is 16px in the previous example — and never changes.

We are converting the widths, 360px and 840px, to rem units by dividing them by 16 because that’s what we assume is the root’s font size. If the user has their preferences set to another root font size, say 18px instead of the default 16px, then that calculation is going to be wrong and the text won’t resize the way we’d expect.

There is only one approach we can use here, and it’s (1) making the necessary calculations in code on page load, (2) listening for changes to the root’s font size, and (3) re-calculating everything if any changes take place.

Here’s a useful JavaScript function to do the calculations:

// Takes the viewport widths in pixels and the font sizes in rem
function clampBuilder( minWidthPx, maxWidthPx, minFontSize, maxFontSize ) {
  const root = document.querySelector( "html" );
  const pixelsPerRem = Number( getComputedStyle( root ).fontSize.slice( 0,-2 ) );

  const minWidth = minWidthPx / pixelsPerRem;
  const maxWidth = maxWidthPx / pixelsPerRem;

  const slope = ( maxFontSize - minFontSize ) / ( maxWidth - minWidth );
  const yAxisIntersection = -minWidth * slope + minFontSize

  return `clamp( ${ minFontSize }rem, ${ yAxisIntersection }rem + ${ slope * 100 }vw, ${ maxFontSize }rem )`;
}

// clampBuilder( 360, 840, 1, 3.5 ) -> "clamp( 1rem, -0.875rem + 8.333vw, 3.5rem )"

I’m deliberately leaving out how to inject the returned string into the CSS because there are a ton of ways to do that depending on your needs and whether your are using vanilla CSS, a CSS-in-JS library, or something else. Also, there is no native event for font size changes, so we would have to manually check for that. We could use setInterval to check every second, but that could come at a performance cost.

This is more of an edge case. Very few people change their browser’s font size and even fewer are going to change it precisely while visiting your site. But if you want your site to be as responsive as possible, then this is the way to go.

For those who don’t mind that edge case

You think you can live without it being perfect? Then I got something for you. I made a small tool to make make the calculations quick and simple.

All you have to do is plug the widths and font sizes into the tool, and the function is calculated for you. Copy and paste the result in your CSS. It’s not fancy and I’m sure a lot of it can be improved but, for the purpose of this article, it’s more than enough. Feel free to fork and modify to your heart’s content.

How to avoid reflowing text

Having such fine-grained control on the dimensions of typography allows us to do other cool stuff — like stopping text from reflowing at different viewport widths.

This is how text normally behaves.

It has a number of lines at a certain viewport width…
…and wraps it’s lines to fit another width

But now, with the control we have, we can make text keep the same number of lines, breaking on the same word always, on whatever viewport width we throw at it.

Viewport width = 400px
Viewport width = 740px

So how do we do this? To start, the ratio between font sizes and viewport widths must stay the same. In this example, we go from 1rem at 320px to 3rem at 960px.

320 / 1 = 320
960 / 3 = 320

If we’re using the clampBuilder() function we made earlier, that becomes:

const text = document.querySelector( "p" );
text.style.fontSize = clampBuilder( 320, 960, 1, 3 );

It keeps the same width-to-font ratio. The reason we do this is because we need to ensure that the text has the right size at every width in order for it to be able to keep the same number of lines. It’ll still reflow at different widths but doing this is necessary for what we are going to do next. 

Now we have to get some help from the CSS character (ch) unit because having the font size just right is not enough. One ch unit is the equivalent to the width of the glyph “0” in an element’s font. We want to make the body of text as wide as the viewport, not by setting width: 100% but with width: Xch, where X is the amount of ch units (or 0s) necessary to fill the viewport horizontally.

To find X, we must divide the minimum viewport width, 320px, by the element’s ch size at whatever font size it is when the viewport is 320px wide. That’s 1rem in this case.

Don’t sweat it, here’s a snippet to calculate an element’s ch size:

// Returns the width, in pixels, of the "0" glyph of an element at a desired font size
function calculateCh( element, fontSize ) {
  const zero = document.createElement( "span" );
  zero.innerText = "0";
  zero.style.position = "absolute";
  zero.style.fontSize = fontSize;

  element.appendChild( zero );
  const chPixels = zero.getBoundingClientRect().width;
  element.removeChild( zero );

  return chPixels;
}

Now we can proceed to set the text’s width:

function calculateCh( element, fontSize ) { ... }

const text = document.querySelector( "p" );
text.style.fontSize = clampBuilder( 320, 960, 1, 3 );
text.style.width = `${ 320 / calculateCh(text, "1rem" ) }ch`;
Umm, who invited you to the party, scrollbar?

Whoa, wait. Something bad happened. There’s a horizontal scrollbar screwing things up!

When we talk about 320px, we are talking about the width of the viewport, including the vertical scrollbar. So, the text’s width is being set to the width of the visible area, plus the width of the scrollbar which makes it overflow horizontally.

Then why not use a metric that doesn’t include the width of the vertical scrollbar? We can’t and it’s because of the CSS vw unit. Remember, we are using vw in clamp() to control font sizes. You see, vw includes the width of the vertical scrollbar which makes the font scale along the viewport width including the scrollbar. If we want to avoid any reflow, then the width must be proportional to whatever width the viewport is, including the scrollbar.

So what do we do? When we do this:

text.style.width = `${ 320 / calculateCh(text, "1rem") }ch`;

…we can scale the result down by multiplying it by a number smaller than 1. 0.9 does the trick. That means the text’s width is going to be 90% of the viewport width, which will more than account for the small amount of space taken up by the scrollbar. We can make it narrower by using an even smaller number, like 0.6.

function calculateCh( element, fontSize ) { ... }

const text = document.querySelector( "p" );
text.style.fontSize = clampBuilder( 20, 960, 1, 3 );
text.style.width = `${ 320 / calculateCh(text, "1rem" ) * 0.9 }ch`;
So long, scrollbar!

You might be tempted to simply subtract a few pixels from 320 to ignore the scrollbar, like this:

text.style.width = `${ ( 320 - 30 ) / calculateCh( text, "1rem" ) }ch`;

The problem with this is that it brings back the reflow issue! That’s because subtracting from 320 breaks the viewport-to-font ratio.

Viewport width = 650px
Viewport width = 670px

The width of text must always be a percentage of the viewport width. Another thing to have in mind is that we need to make sure we’re loading the same font on every device using the site. This sounds obvious doesn’t it? Well, here’s a little detail that could throw your text off. Doing something like font-family: sans-serif won’t guarantee that the same font is used in every browser. sans-serif will set Arial on Chrome for Windows, but Roboto on Chrome for Android. Also, the geometry of some fonts may cause reflow even if you do everything right. Monospaced fonts tend to yield the best results. So always make sure your fonts are on point.

Check out this non-reflowing example in the following demo:

Non-reflowing text inside a container

All we have to do is now is apply the font size and width to the container instead of the text elements directly. The text inside it will just need to be set to width: 100%. This isn’t necessary in the cases of paragraphs and headings since they’re block-level elements anyway and will fill the width of the container automatically.

An advantage of applying this in a parent container is that its children will react and resize automatically without having to set their font sizes and widths one-by-one. Also, if we need to change the font size of a single element without affecting the others, all we’d have to do is change its font size to any em amount and it will be naturally relative to the container’s font size.

Non-reflowing text is finicky, but it’s a subtle effect that can bring a nice touch to a design!

Wrapping up

To cap things off, I put together a little demonstration of how all of this could look in a real life scenario.

In this final example, you can also change the root font size and the clamp() function will be recalculated automatically so the text can have the right size in any situation.

Even though the target of this article is to use clamp() with font sizes, this same technique could be used in any CSS property that receives a length unit. Now, I’m not saying you should use this everywhere. Many times, a good old font-size: 1rem is all you need. I’m just trying to show you how much control you can have when you need it.

Personally, I believe clamp() is one of the best things to arrive in CSS and I can’t wait to see what other usages people come up with as it becomes more and more widespread!


The post Linearly Scale font-size with CSS clamp() Based on the Viewport appeared first on CSS-Tricks.

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

How Do You Do max-font-size in CSS?

CSS doesn't have max-font-size, so if we need something that does something along those lines, we have to get tricky.

Why would you need it at all? Well, font-size itself can be set in dynamic ways. For example, font-size: 10vw;. That's using "viewport units" to size the type, which will get larger and smaller with the size of the browser window. If we had max-font-size, we could limit how big it gets (similarly the other direction with min-font-size).

One solution is to use a media query at a certain screen size breakpoint that sets the font size in a non-relative unit.

body {
  font-size: 3vw;
}
@media screen and (min-width: 1600px) {
  body {
     font-size: 30px;
  }
}

There is a concept dubbed CSS locks that gets fancier here, slowly scaling a value between a minimum and maximum. We've covered that. It can be like...

body {
  font-size: 16px;
}
@media screen and (min-width: 320px) {
  body {
    font-size: calc(16px + 6 * ((100vw - 320px) / 680));
  }
}
@media screen and (min-width: 1000px) {
  body {
    font-size: 22px;
  }
}

We've also covered how it's gotten (or will get) a lot simpler.

There is a max() function in CSS, so our example above becomes a one-liner:

font-size: max(30vw, 30px);

Or double it up with a min and max:

font-size: min(max(16px, 4vw), 22px);

Which is identical to:

font-size: clamp(16px, 4vw, 22px);

Browser compatibility for these functions is pretty sparse as I'm writing this, but Chrome currently has it. It will get there, but look at the first option in this article if you need it right now.

Now that we have these functions, it seems unlikely to me we'll ever get min-font-size and max-font-size in CSS, since the functions are almost more clear as-is.

The post How Do You Do max-font-size in CSS? appeared first on CSS-Tricks.

Simplified Fluid Typography

Fluid typography is the idea that font-size (and perhaps other attributes of type, like line-height) change depending on the screen size (or perhaps container queries if we had them).

The core trickery comes from viewport units. You can literally set type in viewport units (e.g. font-size: 4vw), but the fluctuations in size are so extreme that it's usually undesirable. That's tampered by doing something like font-size: calc(16px + 1vw). But while we're getting fancy with calculations anyway, the most common implementation ended up being an equation to calculate plain English:

I want the type to go between being 16px on a 320px screen to 22px on a 1000px screen.

Which ended up like this:

html {
  font-size: 16px;
}
@media screen and (min-width: 320px) {
  html {
    font-size: calc(16px + 6 * ((100vw - 320px) / 680));
  }
}
@media screen and (min-width: 1000px) {
  html {
    font-size: 22px;
  }
} 

That's essentially setting a minimum and maximum font size so the type won't shrink or grow to anything too extreme. "CSS locks" was a term coined by Tim Brown.

Minimum and maximum you say?! Well it so happens that functions for these have made their way into the CSS spec in the form of min() and max().

So we can simplify our fancy setup above with a one-liner and maintain the locks:

html {
  font-size: min(max(16px, 4vw), 22px);
}

We actually might want to stop there because even though both Safari (11.1+) and Chrome (79+) support this at the current moment, that's as wide as support will get today. Speaking of which, you'd probably want to slip a font-size declaration before this to set an acceptable fallback value with no fancy functions.

But as long as we're pushing the limits, there is another function to simplify things even more: clamp()! Clamp takes three values, a min, max, and a flexible unit (or calculation or whatever) in the middle that it will use in case the value is between the min and max. So, our one-liner gets even smaller:

body {
  font-size: clamp(16px, 4vw, 22px);
} 

That'll be Chrome 79+ (which doesn't hasn't even dropped to stable but will very soon).

Uncle Dave is very happy that FitText is now a few bytes instead of all-of-jQuery plus 40 more lines. Here is us chucking CSS custom properties at it:

See the Pen
FitText in CSS with clamp()
by Dave Rupert (@davatron5000)
on CodePen.

The post Simplified Fluid Typography appeared first on CSS-Tricks.

Using a PostCSS function to automate your responsive workflow

A little while back, you might have bumped into this CSS-Tricks article where I described how a mixin can be used to automate responsive font sizes using RFS. In its latest version, v9, RFS is capable of rescaling any value for value for any CSS property with px or rem units, like margin, padding, border-radius or even box-shadow.

Today, we’ll focus on its PostCSS implementation. Continue reading "Using a PostCSS function to automate your responsive workflow"

Using a Mixin to Take the Math out of Responsive Font Sizes

Responsive Font Size (RFS) is an engine that automatically calculates and updates the font-size property on elements based on the dimensions of the browser viewport.

If you’re thinking that sounds familiar, that’s because there is a slew of tools out there that offer various approaches for fluid typography. In fact, Chris compiled a bunch of those a little while back. Check that out because it’s always good to know what’s out there and what fits best for a particular task.

RFS is different in that it makes writing code for fluid type feel a lot like writing native CSS (or, more accurately, like writing with a preprocessor) directly in the stylesheets you’re already working in — only without having to wrangle and manage a bunch of media queries. It’s even compatible with Sass, Less, Stylus and PostCSS, so it plugs into just about any stack.

Just how integrated is it? Well, let’s compare a snippet for fluid typography that uses the calc() function...

html {
  font-size: 16px;
}

@media screen and (min-width: 320px) {
  html {
    font-size: calc(16px + 6 * ((100vw - 320px) / 680));
  }
}

@media screen and (min-width: 1200px) {
  html {
    font-size: 22px;
  }
}

...with a similar example of how it can be done with RFS in Sass:

.title {
  @include font-size(4rem);
}

Which compiles to:

.title {
  font-size: 4rem;
}

@media (max-width: 1200px) {
  .title {
    font-size: calc(1.525rem + 3.3vw);
  }
}

Curious how that works? Let’s check it out and then go into how to set it up for a project.

The magic behind automatic re-scaling

Here’s a graph to get a better understanding of how RFS re-scales font sizes:

Every color represents a font size that gets passed to the font-size() mixin provided by RFS. The y-axis of the graph represents the font size (in px) and the x-axis represents the width of the viewport (again, in px).

Let’s focus on the green line, which is generated by applying a mixin to an element:

.title {
  @include font-size(40);
}

In this case, a font size of 40px is passed into the mixin. That value serves as the maximum font size of the element and reaches that size when the viewport is 1200px or wider, at which point it stays at that size.

Conversely, the font size will bottom out at 20px, never going below that mark.

Everything else? Well, that’s where the font size value is automatically calculated, using a function behind the scenes to determine the number according to the current width of the viewport.

RFS is also a little opinionated in that it limits itself to font sizes that are 20px and above. The reasoning is that smaller text (e.g. normal body text) normally does not need to flex as much and is a lot easier to manage than larger pieces of content, like titles and such. That’s very much in line with FitText, which also prefers being used on large text (even though it will not stop you from doing it).

If you’re the type of person who likes to look under the hood, the mixin for each preprocessor is available to view in the RFS GitHub repo. For example, here’s a direct link to the SCSS version. It’s a lot of math!

Note that every font size is generated in a combination of rem and vw units, but they are mapped to px in the graph to make it easier to understand. In other words, it really takes all the mathwork out of the mix.

Everything is configurable

Seriously. Every. Single. Thing.

For example, you may have wondered why the font size capped out at viewports 1200px and wider in the previous example. That can be changed, as well as a ton of other things, including:

  • Base font size: The lowest font size value.
  • Font size unit: The type of unit to use in the output value (px or em).
  • Breakpoint: The maximum width of the viewport where the font size of the element reaches its maximum value.
  • Breakpoint unit: The unit used for the media query that the mixin generates (px, em or rem).
  • Factor: This serves as a sorta volume control that informs the mixin how aggressive it should be in calculating font sizes from the maximum viewport width all the way down.
  • Rem value: This defines the value of 1rem in pixel (px) units.
  • Two dimensional: A feature that sniffs out the smallest side of a viewport and uses it to calculate the font size value. This comes in handy when, say, you’d like to keep the font from getting smaller when a device is rotated from a portrait orientation to landscape.
  • Class: Provides class names that can be added to an element in the HTML to either enable or disable fluid sizing.

So, yeah. A lot of options and flexibility here. The important thing to know is that all of these options are variables that can be defined in your stylesheets.

All this said, the default settings are pretty safe to use, and they will prevent a lot of longer words truncating from the viewport. This is especially true for some languages — like German or Dutch — that contain a lot of compound words.

Using RFS in a project

Let’s dive straight into to the code. It would be exhaustive to look at the code for each preprocessor, so I’ll be explaining everything in the .scss syntax. But if you prefer something else, you can check out the examples in other languages in the GitHub repo in the Usage section.

First and foremost, RFS needs to be installed on the project. It’s available in npm and Yarn:

## npm
npm install rfs

## Yarn
yarn add rfs

## Bower is available, but has been deprecated
bower install rfs --save

Then, gotta make sure the mixin is imported with the rest of the styles, wherever you do your imports for other partials:

@import "~rfs/scss";

Now, we can start cooking with the mixin!

.title {
  color: #333;
  @include font-size(64px);
}

.subtitle {
  color: #666;
  @include font-size(48px);
}

.paragraph {
  @include font-size(16px);
}

I passed values in px, but rem units are also supported. If a value without a unit is passed, px is used by default. The font sizes are always rendered in rem (in combination with vw) to make sure the font sizes also increase when the default font size is increased in the browser (this is a feature often used by visually impaired people).

The output is:

.title {
  color: #333;
  font-size: 4rem;
}

@media (max-width: 1200px) {
  .title {
    font-size: calc(1.525rem + 3.3vw);
  }
}

.subtitle {
  color: #666;
  font-size: 3rem;
}

@media (max-width: 1200px) {
  .subtitle {
    font-size: calc(1.425rem + 2.1vw);
  }
}

.paragraph {
  font-size: 1rem;
}

Notice that the mixin is font-size(), but RFS will also let you use it in two other ways:

.title {
  @include font-size(4rem);
  // or
  @include responsive-font-size(64px);
  // or
  @include rfs(64);
}

RFS is baked right into Bootstrap

Here’s a little story for you.

One day, I had this incredibly impulsive idea to put RFS into Bootstrap. I actually did not use Bootstrap at that time, but believed it was a feature Bootstrap could definitely use. I made a pull request and waited a couple months to see what would happen.

In the meantime, I was getting more and more intrigued by Bootstrap and version 4 had just been released. Slowly but surely, I got more involved in contributing to the project and a whole new world opened for me when I discovered the community behind it. It was during hacktoberfest (oh yes, I got my t-shirt) in October 2018 that I got asked to join the Bootstrap team by mdo.

I believe contributing to open source projects is such a fun and rewarding thing. Andrés Galante has a great post on the topic if you're interested in becoming a contributor.

Since then, RFS has become a project of the Bootstrap team, and on February 11th this year, we launched Bootstrap 4.3 which includes RFS right out of the box. It’s currently disabled by default, but can easily be switched on by setting the Sass variable $enable-responsive-font-sizes: true.

But make no mistake: RFS can still be used on its own. Just cool that it's baked right into a widely used framework.

Oh yeah, let's talk browser support

Support is pretty darn good! In fact, RFS will work anywhere that supports media queries and viewport units. RFS will set a font size for Legacy browsers, like Internet Explorer 8, but the fluidity won't be there. In other words, should be safe for production!

What’s next for RFS

The next major version of Bootstrap is version 5 and we’re planning to enable RFS by default. We don’t have any plans to change the way it works for now. More than likely, the $enable-responsive-font-sizes variable will simply be set to true and that’s it.

In the future, I hope I can make use of the min() function because it would generate less CSS and make things a lot less complex. Browsers don’t seem to support this function all too well just yet, but if you’re interested in this feature, you can follow the progress in this GitHub issue.

Anything else? No, but I can leave you with a little song and dance: Na na na na, na na na na, hey hey hey goodbye!

The post Using a Mixin to Take the Math out of Responsive Font Sizes appeared first on CSS-Tricks.

Well, Typetura seems fun

I came across this update from Scott Kellum's and Sal Hernandez's project Typetura via my Medium feed this morning, and what a delight?!

(Also, wow, I really have been out of the game for a minute.)

This is quite exciting! Typetura wants to deal with some of the main problems that come up when utilizing fluid type in your CSS.

Typetura was created to make fluid typography mainstream. To do this there were two problems to solve. First, develop an implementation that is feature rich and easy to implement with CSS. Second, create a design tool that designers can use to illustrate how they want fluid typography to look.

I love a tool that tries to remove friction and make technologies easier to use.

To ensure the implementation was easy to use and understand, Typetura needed a simple, declarative syntax in vanilla CSS. This means no complicated math or Sass tricks.

Design software is constructed around fixed art boards, but there needs to be a way for designers to communicate how designs transition between sizes... Typetura is a tool that enables designers to work with a fluid canvas.

Direct Link to ArticlePermalink

The post Well, Typetura seems fun appeared first on CSS-Tricks.