Front End Web Development

Read Me!

Css Tricks - Fri, 09/11/2020 - 1:30pm

A fancy experiential essay from the team at Readymag, which is a tool for building… fancy experiential essays, about fancy experiential essays:

With all the technology addressing readability issues, it’s still design basics that distinguish a readable text from one that isn’t. Here are some simple rules we use ourselves when developing engaging texts and layouts.

I like this advice:

Always start with quality writing.

I find that it’s not only longform that inspires a fancy “art directed” post around here, but quality writing.

I can’t decide if I like that the URL changes as you scroll down the article. Seems a little better suited to hash links.

Direct Link to ArticlePermalink

The post Read Me! appeared first on CSS-Tricks.

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

Using a brightness() filter to generically highlight content

Css Tricks - Fri, 09/11/2020 - 12:29pm

Rick Strahl:

I can’t tell you how many times over the years I’ve implemented a custom ‘button’ like CSS implementation. Over the years I’ve used images, backgrounds, gradients, and opacity to effectively ‘highlight’ a control. All that works of course, but the problem with most of these approaches is that one way or the other you’re hard coding a color value, image, or gradient.

You certainly have a lot more control if you specify exact colors, but if you can pull off brightening, darkening, or even a hue-shift in a way that feels cohesive on your site, it’s certainly a lot less code to maintain,

.button.specific-button { background: #4CAF50; } .button.specific-button:focus, .button.specific-button:hover { background: #A5D6A7; } /* vs. */ .button:focus, .button:hover { filter: brightness(120%); } /* or maybe you're super hardcore and do it everywhere */ :focus, :hover { filter: brightness(120%) saturate(120%); }

Direct Link to ArticlePermalink

The post Using a brightness() filter to generically highlight content appeared first on CSS-Tricks.

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

Defining “View Source”

Css Tricks - Thu, 09/10/2020 - 10:39am

Last time there was a little flurry of activity around the concept of “View Source,” I did get the sense that not everyone was on the same page about what that even means. Jim Nielsen:

First, when we talk about “View Source” what precisely are we talking about? I think this is an important point to clarify, as it sometimes goes unsaid and therefore a lot of assumptions sneak into the conversation and we might realize we’re not all talking about the same thing.

There are three things that people might be talking about:

  1. View source code (the code that generates the HTML delivered over the network)
  2. View page source (the HTML delivered over the network)
  3. View runtime source (the living HTML, a.k.a the DOM)

I’ll assign what I think are the values of each are, as slices of a pie chart:

  1. 10%
  2. 5%
  3. 85%

Every major browser ships with built-in DevTools where you can easily peak at the “runtime source.” That’s where the vast bulk of value is to me. If browsers ever talked about removing that, I’m sure we’d all be up in arms. Even for non-developers, the existence of this tool might be the spark that grows baby web developers.

DevTools also provides a way to view the HTML delivered over the network, hence my hardline stance from before:

I literally don’t care at all about View Source and wouldn’t miss it if it was removed from browsers. I live in DevTools, and I’ll bet you do too. It entirely supersedes View Source, as you can quite literally view source inside it if you’d like.

Jim’s post explains the difference between all three types of “viewing source” in great detail. For sites that are built entirely from client-side JavaScript, viewing the HTML over the wire is nearly useless. But if you could see the whole codebase (say if it was open-source on GitHub), there is certainly value there.

Direct Link to ArticlePermalink

The post Defining “View Source” appeared first on CSS-Tricks.

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

Modifying Specific Letters with CSS and JavaScript

Css Tricks - Thu, 09/10/2020 - 4:40am

Changing specific characters can be a challenge in CSS. Often, we’re forced to implement our desired changes one-by-one in HTML, perhaps using the span element. But, in a few specific cases, a CSS-focused solution may still be possible. In this article, we’ll start by looking at some CSS-first approaches to changing characters, before considering a scenario where we need to turn to JavaScript.


Right now, CSS doesn’t excel at targeting specific characters without making alterations to the HTML. However, there are a few scenarios where CSS could be the go-to.


The @font-face rule is regularly used to create custom fonts, but its unicode-range property can also allow us to target specific characters. 

For example, imagine our site often contains ampersands in its headings. Instead of using the heading font, we want something a tad more flamboyant. We can look up the unicode value of an ampersand (U+0026) and use unicode-range to target this specific character.

@import url(''); h1, h2, h3, h4, h5, h6 {   font-family:  'Ampersand', Montserrat, sans-serif; } @font-face {   font-family: 'Ampersand';   src: local('Times New Roman');   unicode-range: U+0026; }

Try this with the following HTML to see it in action:

<h1>Jane Austen Novels</h1> <h2>Pride & Prejudice</h2> <h2>Sense & Sensibility</h2> ::first-letter

The ::first-letter pseudo-element was primarily designed with drop caps in mind and it is supported by all major browsers.

p::first-letter {   font-size: 125%;   font-weight: bold; }

Of course, this is only useful in a relatively limited number of scenarios. There have been several calls for an  ::nth-letter pseudo-element (including here on CSS-Tricks) but, right now, that’s just a pipe dream!


Using the ::after pseudo-element and content property, we can achieve a similar effect for the final character — so long as that character is always the same. For example, here’s how we could add a jazzy, italicized exclamation point after every h2 element:

h2::after {   content: '\0021';   color: red;   font-style: italic; } font-variant-alternates

Finally, there’s the font-variant-alternates property. This is only supported by Firefox, so it’s not recommended for production, but it may be worth knowing about for really specific scenarios: if a font happens to contain alternate glyphs, we can use this property with the character-variant() function to select a preferred glyph for a character of our choice.


Turning to JavaScript doesn’t need to come at a cost to performance, especially if we run HTML-altering functions at build time. The most common use case is probably to find and replace specific characters in our HTML with a span element. For simplicity’s sake, I’ll begin with an example on the client-side, and after that we’ll look into running this at build with webpack.

Find and replace at runtime

Let’s imagine that, whenever we have the text “LOGO” in a header on our site, we want to add a special style to the first “O” character only, by wrapping it in a span element with the class .special-o.

const headings = document.querySelectorAll("h1, h2, h3, h4, h5, h6"); for (const heading of headings) {   heading.innerHTML = heading.innerHTML     .replace(/\bLOGO\b/g, 'L<span class="special-o">O</span>GO'); }

In the JavaScript above, we’re performing a find-and-replace on every heading tag. 

Our regular expression uses the metacharacter \b to ensure that LOGO is always a word — rather than an element of a larger word. For example, we don’t want to match the plural  “LOGOS.” Right now, it would be impossible to do this with CSS, not least because we only want to target the first “O” in the sequence.

The same principle applies if we want to replace the “O” — or even the whole word “LOGO” — with an image. 

Find and replace at build

There are plenty of build tools out there, but as webpack is so popular, we’ll use that for our example — and luckily, there’s a plugin for what we need called string-replace-loader. For those new to webpack, a loader is used to preprocess files. Here, we can perform a find-and-replace on specific files as part of our build. 

First, we need to install the plugin:

npm install --save-dev string-replace-loader

Then, inside webpack.config.js add:

module.exports = {   // ...   module: {     rules: [       {         test: /\.html$/i,         loader: 'string-replace-loader',         options: {           search: '/\bLOGO\b/g',           replace: 'L<span class="special-o">O</span>GO',         }       }     ]   } }

By changing the test property value, we could target JSX, TSX, PUG, Handlebars or any other templating file format:

/\.html$/i # HTML /\.[jt]sx$/i # JSX or TSX /\.pug$/i # PUG /\.handlebars$/i # Handlebars

The advantage of this approach is that no unnecessary JavaScript will run in our client’s browser. 

Final note

Finally, if you’re comfortable creating and editing fonts and would rather avoid CSS or JavaScript, a custom font could be a solution for many of the scenarios set out above. There are plenty of free font-editing tools such as Font Forge or Birdfont for those who want to try this more design-focused approach.

The post Modifying Specific Letters with CSS and JavaScript appeared first on CSS-Tricks.

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

Setting up and Customizing the Ant Design System in a Nuxt App

Css Tricks - Wed, 09/09/2020 - 9:46am

I don’t typically work with UI libraries because they can be cumbersome and hard to override, which can contribute to a bloated. However, Ant Design has recently gained some some of my affection because it’s easy to use, has extensible defaults, and features a delicate design.

Nuxt and Ant Design work well together, in part because of Nuxt’s code-splitting and tree-shaking abilities, not to mention Nuxt’s new static target deployment option. I can serve an app using Ant Design with great performance scores.

Combining the two was a little tricky and there isn’t a lot in the way of documentation for how to do it, so what follows are the steps you need to set it up. Let’s get started!


The first step is installing the ant-design-vue package, along with Less.js and less-loader, which we will need to create our Less variables:

yarn add ant-design-vue less less-loader # or npm i ant-design-vue less less-loader

Now lets tell Nuxt to use it globally via a plugin. We’ll create a file called antd-ui.js:

import Vue from 'vue' import Antd from 'ant-design-vue/lib' Vue.use(Antd)

You may notice that unlike the process outlined in the Ant Design getting started guide, we are not importing the global CSS file they mention. That’s because we’re going to manually import the base variable Less file instead so that we can override it. 

We have a few things to do in our nuxt.config.js file. First, let’s register the plugin we just made:

plugins: ["@/plugins/antd-ui"],

Next, we’re going to let webpack know we’d like to build Less:

build: { loaders: { less: { lessOptions: { javascriptEnabled: true, }, }, }, }

Finally, we need to create a global stylesheet for our variables that imports Ant Design’s defaults as well as our overrides:

css: [ "~/assets/variables.less" ],

We can see that this file exists in a /assets folder, so let’s make it. We’ll create a file in there called variables.less, and import Ant Design’s Less variables:

@import '~ant-design-vue/dist/antd.less';

Below this line, there are myriad variables you can override. This is just a sampling. The rest of the variables are here, and you’ll need to include them by their @ and can change it to whatever you wish:

@primary-color: #1890ff; // primary color for all components @link-color: #1890ff; // link color @success-color: #52c41a; // success state color @warning-color: #faad14; // warning state color @error-color: #f5222d; // error state color @font-size-base: 14px; // major text font size @heading-color: rgba(0, 0, 0, 0.85); // heading text color @text-color: rgba(0, 0, 0, 0.65); // major text color @text-color-secondary: rgba(0, 0, 0, 0.45); // secondary text color @disabled-color: rgba(0, 0, 0, 0.25); // disable state color @border-radius-base: 4px; // major border radius @border-color-base: #d9d9d9; // major border color @box-shadow-base: 0 2px 8px rgba(0, 0, 0, 0.15); // major shadow for layers

We’re good to go! There’s no need to import what we need into every component because Nuxt will now take care of that. If you’d like to override very specific styles not included in the variables, you can find the associative classes and override them in your layouts/default.vue file as well. and Nuxt allow you a great framework for building apps very quickly and with ease. Enjoy!

The post Setting up and Customizing the Ant Design System in a Nuxt App appeared first on CSS-Tricks.

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

The argument that kills any monetisation discussion

QuirksBlog - Wed, 09/09/2020 - 1:38am

When I was going through Stephanie Rieger’s presentation about regulation for the web, I had an idea: what if we forced people to pay for social media use?

Today I’d like to discuss not that idea but a counterargument leveled against it: What about people who cannot afford to pay for social media? Wouldn’t they be left behind? This observation turns up sooner or later in any monetisation discussion.

I have a problem with this argument.

Killing the discussion

My problem is not that it’s untrue — I wish it were; that would make any monetisation discussion a lot easier.

My problem is that it effectively kills the discussion.

Giving in to this argument raises the interests of people who are unable to pay to the top of our priority list, trumping the interests of other constituencies, notably content creators. If we accept this argument in full, we are effectively unable to make any further progress — or so it seems to me.

The current system of giving away everything for free benefits people who are unable to pay. That is a good feature, but I feel that the fact that a system has a good feature does not mean we should accept all of the bad ones.

In order to change the status quo we have to temporarily ignore the interests of people who are unable to pay. Considering them, and drawing up plans in case of a (so-far hypothetical) victory of sane monetisation is fine. Killing the discussion in their name is not.

That’s why in the future I am going to respectfully reject this argument while acknowledging it is true. The fact that some people are not able to pay for monetisation scheme X is a problem to be solved, but it is not a reason to reject scheme X.

Paying for access

Assume for a moment that sites like this, or, much more importantly, MDN, require payment, or at least that there is strong social pressure to pay for usage. Some people are unable to do so. How should we solve that problem?

To me, the answer is obvious: create a sort of fund that buys subscriptions wholesale (with a bit of bulk discount?) and dontes them to affected people.

I don’t know a lot about such funds, but I do have ample experience with diversity tickets for conferences, which is a somewhat-comparable use case. In our experience, gathering the money to pay for a few diversity tickets is no problem. Companies will chip in, some speaker will waive their fees, or sometimes even their travel budgets, we’ll give a discount and add one or two free tickets, and before we know it we have enough budget for about ten diversity tickets.

Access costs less money per person than a diversity ticket, although we need many more units. That’s why I am assuming that acquiring the budget to pay for access for even a few hundred people is quite possible, although it may take some time.


The problem lies in the selection. Who exactly should receive support from this fund?

This is usually the bottleneck for our diversity tickets, because we decided long ago that we ourselves are not going to take that decision. We used to use a service that made a selection for us, but even before the Corona crisis broke they decided to cease their selection service. That leaves ... nothing, as far as we know.

A hypothetical system that pays for access to content would run into the same problem. Who deserves such support? Who decides who deserves such support? Somebody will have to take decisions here, will have to — dare I say it? — keep the gate.

But who? To me, this is the crucial question. I have no easy answer.

If you have an answer please share it. Note, however, that I’m looking for something structural, something that can stay in place for years and years to come. Right now I’m not interested in temporary solutions.

Or do we want to keep the current system in place so that we don’t have to answer this question?

Or am I worrying too much and will the situation sort-of solve itself? Am I maybe erecting a straw-man argument? I just don’t know right now.


As to my original idea of paying for social media usage, feel free to think about it, ask hard questions like Dean Bubley did, and mull it over in your head, but the more I think about it, the more I feel that it’s too complicated to actually execute.

AVIF has landed

Css Tricks - Tue, 09/08/2020 - 11:19am

Everybody is talking about AVIF today because of Jake’s blog post. As the say, I was today years old when I learned AVIF was a thing. But thanks to web technology being ahead of the game for once, we can already take advantage of it.

This will be easier if you’ve abstracted your responsive images syntax. Wherever you’re using <picture> you can slip it in such that supporting browsers get it and non-supporting do not:

<picture> <!-- use if possible --> <source type="image/avif" srcset="snow.avif"> <!-- fallback --> <img alt="Hut in the snow" src="snow.jpg"> </picture>

Wanna play with it right now? Jake updated Squoosh to support it. CodePen also supports it. Here’s a Pen (I forked off Shaw’s original):

CodePen Embed Fallback

Check out the Pug HTML there to flop out other sources. If the URL to the image you put it is hosted on CodePen’s Asset Hosting, it will do all the conversions and such automatically. The images go through a Cloudflare Worker which is what does the conversions, and supports AVIF. For new images, you might feel the response time lag on that first request for AVIF before it is cached, seems like generating them takes a lot more work.

Like any format, it really depends on the type of image it is. While screwing around, I put an already-compressed JPG as the source, and AVIF more than doubled the size of it’s version. So you’ll have to be careful that you aren’t making things slower by using it.

We’ve had it good with new image formats so far. WebP is nearly always the best format so much of the logic has gone down the if (webp_supported) { use_webp } road. But now, not only is AVIF only sometimes smaller, the way it does compression leads to different visual results, so even when it is smaller, you might not be happy with the look.

My ideal scenario is always some kind of image CDN with ?format=auto&quality=auto where it picks the best possible format and quality automatically, never making it worse than the original. But then also having overrides possible so if you aren’t happy with an automatic decision, you can fix it. I was going to test Cloudinary’s auto-formatting choices, but they aren’t supporting it yet. I’d bet they will soon, but I also bet it’s darn complicated to get right.

Direct Link to ArticlePermalink

The post AVIF has landed appeared first on CSS-Tricks.

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

One Action, Multiple Terminal Windows Running Stuff

Css Tricks - Tue, 09/08/2020 - 10:06am

Many development environments require running things in a terminal window. npm run start, or whatever. I know my biggest project requires me to be running a big fancy Docker-based thing in one terminal, Ruby on Rails in another, and webpack in another. I’ve worked on other projects that require multiple terminal windows as well, and I don’t feel like I’m that unusual. I’ve heard from several others in this situation. It’s not a bad situation, it’s just a little cumbersome and annoying. I’ve got to remember all the commands and set up my command line app in a way that feels comfortable. For me, splitting panels is nicer than tabs, although tabs for separate projects seems OK.

I asked the question on Twitter, of course. I figured I’d compile the options here.

  • tmux was the most popular answer. I’m very sure I don’t understand all it can do, but I think I understand that it makes “fake” panes within one terminal session that emulates multiple panes. So, those multiple panes can be configured to open and run different commands simultaneously. I found this interesting because it came literally days later my CodePen co-founder let us all know the new dev environment he’s been working on will use tmux.
  • I was pointed to kitty by a fella who told me it feels like a grown-up tmux to him. It can be configured into layouts with commands that run at startup.
  • There are native apps for all the platforms that can run multiple panels.
    • macOS: I’ve long used iTerm which does split panels nicely. It can also remember window arrangements, which I’ve used, but I don’t see any built-in option for triggering commands in that arrangement. The native terminal can do tabs and splitting, too, but it feels very limited.
    • Linux: Terminator
    • Windows: The default terminal has panes.
  • There are npm things for running multiple scripts, like concurrently and npm-run-all, but (I think?) they are limited to running only npm scripts, rather than any terminal command. Maybe you can make npm scripts for those other commands? But even then, I don’t think you’d see the output in different panels, so it’s probably best for scripts that are run-and-done instead of run-forever.

Being a Mac guy, I was most interested in solutions that would work with iTerm since I’ve used that anyway. In lieu of a built-in iTerm solution, I did learn it was “scriptable.” Apparently, they are sunsetting AppleScript support in favor of Python but, hey, for now it seems to work fine.

It’s basically this:

The Code tell application "iTerm" tell current window create window with default profile tell current session of current tab set name to "" write text "cd '/Users/chriscoyier/GitHub/CPOR'" write text "./" end tell create tab with default profile tell current session of current tab set name to "Rails" write text "cd '/Users/chriscoyier/GitHub/CPOR'" write text "nvm use" write text "yarn" write text "bundle install" write text "yarn run rails" end tell create tab with default profile tell current session of current tab set name to "webpack" write text "cd '/Users/chriscoyier/GitHub/CPOR'" write text "nvm use" write text "yarn" write text "yarn run dev" end tell # split vertically # tell application "System Events" to keystroke "d" using command down # delay 1 # split horizontally # tell application "System Events" to keystroke "d" using {shift down, command down} # delay 1 # moving... (requires permission) # tell application "System Events" to keystroke "]" using command down end tell end tell

I just open that script, hit run, and it does the job. I left the comments in there because I’d like to figure out how to get it to do split screen the way I like, rather than tabs, but I got this working and then got lazy again. It felt weird to have to use keystrokes to have to do it, so I figured if I was going to dig in, I’d figure out if their newer Python stuff supports it more directly or what. It’s also funny I can’t like compile it into a little mini app or something. Can’t Automator do that? Shrug.

The other popular answer I got for Mac folks is that they have Alfred do the work. I never got into Alfred, but there clearly is fancy stuff you can do with it.

The post One Action, Multiple Terminal Windows Running Stuff appeared first on CSS-Tricks.

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

Jetpack 8.9: Take Donations, Capture Email Subscribers, AMP integration, and More

Css Tricks - Tue, 09/08/2020 - 9:37am

(This is a sponsored post.)

Jetpack 8.9 shipped on September 1 and it shows why the plugin continues to be the premier way to take a WordPress site from good to holy smokes! Several new features are packed into the release, but a few really stand out.

Take donations with a new block

The first is donations, and a quick demo of how easy it is to drop a donation form into a page is going to excite anyone who has ever had to cobble together multiple third party scripts and tools to get something like this on a site.

That’s right — it’s as easy as any other block and it connects directly to your Stripe account when you upgrade to a Jetpack paid plan. Non-profits are sure to love this, but even if you’re a plugin developer looking for a way to collect “tips” in exchange for your work, you’ll get a lot of mileage out of something like this.

I’d drop a donations block right here to show you, but if you’re so inclined (&#x1f60d;) we have a MVP supporter thing set up that handles that, which is powered by WooCommerce Memberships.

Collect newsletter signups and automate email marketing

Another feature that stands out is a newsletter signup form. Instead of relying on another plugin for form functionality and another to connect the form to an email newsletter service, Jetpack handles it all with a new block that not only collects subscribers, but integrates directly with Creative Mail by Constant Contact.

That means you not only take signups directly from your site, but you get a way to pull WordPress content and WooCommerce products into emails that support all kinds of automatons, like scheduled sends, action-based triggers, and multi-step marketing journeys. It’s a lot of power in a single package!

It’s worth noting that the newsletter form is in addition to a growing number of forms that are built right into Jetpack, including RSVP, contact, registration, feedback, and appointments.

AMP-ify your content

There isn’t a whole lot of details on this feature, but it certainly warrants attention. Automattic and Google have been working closely together the past several months to ship the 2.0 version of the official AMP plugin for WordPress.

The plan is for the Jetpack team to write up a detailed post sometime soon that thoroughly outlines the integration. Just a guess? Perhaps Jetpack blocks will natively support valid AMP markup in way that maintains the functionality while meeting AMP’s performance standards. We’ll see!

Jetpack 8.9 is the latest release in what’s proving to be a rapidly evolving one-stop shop for the most common and useful WordPress features that normally would require plugin overload. The past year alone has seen a slideshow block, on-site instant search, built-in customer relationship management and security monitoring — and those are just the highlights! You really can’t go wrong with Jetpack if you’re looking for the most powerful set of features in one place. Plug it in, purchase a plan, and you get access to literally dozens of features and enhancements for WordPress without having to hunt them down, one-by-one. Hey, that’s why we use Jetpack around here at CSS-Tricks… and love it!

Direct Link to ArticlePermalink

The post Jetpack 8.9: Take Donations, Capture Email Subscribers, AMP integration, and More appeared first on CSS-Tricks.

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

All the Ways to Make a Web Component

Css Tricks - Mon, 09/07/2020 - 10:45am

This is a neat page that compares a ton of different libraries with web components. One of the things I learned after posting “A Bit on Web Components Libraries” is that the web platform APIs were designed for libraries to be built around them. Interesting, right?

This page makes a counter component. By extending HTMLElement natively, they do it in 1,293 bytes, then each library adds things on top of that. The big libraries, like Vue and React, are clearly much bigger (but bring a ton of other functionality to the table). One of the biggest is CanJS (230,634 bytes), which isn’t aiming to be small, but, from their about page: “It targets experienced developers building complex applications with long futures ahead of them.” If the goal is small, Svelte is true to its mission of nearly compiling itself away ending at just 3,592 bytes, a third of the size of the super tiny lit-html and half the size of uhtml — both of which are just tiny abstractions that offer nicer templating and re-rendering.

Direct Link to ArticlePermalink

The post All the Ways to Make a Web Component appeared first on CSS-Tricks.

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

Import Non-ESM libraries in ES Modules, with Client-Side Vanilla JS

Css Tricks - Mon, 09/07/2020 - 10:45am

We’re living through a weird era where there are tons of JavaScript libraries that were meant to be used as <script> tags that expose available globals. AND there are tons of JavaScript libraries that are meant to be used through module loaders. AND there are tons of JavaScript libraries that assume you will use them via npm. AND there are tons of libraries built for ES6 imports. If you write a JavaScript library and are shooting for maximum usage, you’d make it work in all those ways, even though that’s obnoxious legwork.

I love Lea’s ideas here on taking libraries that were never really meant to be ES6 import-ed, but doing it anyway.

For example:

window.module = {}; import("").then(_ => { console.log(module.exports); });

And a function if you needed to be safer about that, like a little abstraction:

CodePen Embed Fallback

Check out the article for another clever little trick.

Direct Link to ArticlePermalink

The post Import Non-ESM libraries in ES Modules, with Client-Side Vanilla JS appeared first on CSS-Tricks.

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

Using max() for an inner-element max-width

Css Tricks - Mon, 09/07/2020 - 5:37am

I go into all this in The “Inside” Problem. The gist: you want an edge-to-edge container, but the content inside to have a limited width. I think there is absolutely no problem using a nested element inside, but it’s also fun to look at the possibilities of making that work on a single element.

My favorite from that article is this one that calculates padding for you:

CodePen Embed Fallback

While calc() does indeed do the trick, it doesn’t allow you to have a minimum padding. Well, max() does. I still find it hella confusing that we reach for max() when we want a minimum value but, hey, just gotta build that muscle memory.

Reader Caluã de Lacerda Pataca responded to our last newsletter where we mentioned these functions with a this clever idea:

CodePen Embed Fallback

Now we can make sure that the content doesn’t smash up against the edges no matter what.

The post Using max() for an inner-element max-width appeared first on CSS-Tricks.

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

Supercharging Number Inputs

Css Tricks - Fri, 09/04/2020 - 4:46am

Speaking of number scrubbing (i.e. adding mouse UX to number inputs), you can also add better keyboard commands to number inputs. Kilian Valkhof explains how he added up and down arrows to a number input, as well as modifier keys to change how much the keys increment the value, like Emmet does.

This would make a nice little web component.

Direct Link to ArticlePermalink

The post Supercharging Number Inputs appeared first on CSS-Tricks.

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

Stroke Text CSS: The Definitive Guide

Css Tricks - Thu, 09/03/2020 - 12:52pm

Whenever I think of stroked text on the web I think: nope.

There is -webkit-text-stroke in CSS for it, but it places that stroke in the middle of the vector outline of the characters, absolutely ensuring that the character doesn’t look right. Just look at this in Chrome or Safari. Gross. If you’re going to do it, at least layer the correct type on top so it has its original integrity. And even then, well, it’s non-standard and you don’t get cross-browser support.

John Negoita covers text stroke in a bunch of other ways. Another way to fake it is to use text-shadow in multiple directions.

Four ways, like the figure above, doesn’t usually cut it, so he gets mathy with it. SVG is capable of doing strokes, which you’d think would be much smarter, but it has the same exact problem as CSS does with the straddled stroke — only with somewhat more control.

I’d probably avoid stroked text on the web in general, unless it’s just a one-off, in which case I’d make it into SVG in design software, fake the stroke, and use it as a background-image.

It is possible to look cool.

Direct Link to ArticlePermalink

The post Stroke Text CSS: The Definitive Guide appeared first on CSS-Tricks.

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

Prints & Propa­ganda

Typography - Thu, 09/03/2020 - 5:44am

Read the book, Typographic Firsts

By the sixteenth century, printmaking — or art prints — had become a burgeoning industry in Europe. Millions were printed and many thousands have survived until the present day. Their significance goes well beyond their value as art or artifact, revealing a great deal more than artists' talents and virtuosity. A closer look at their subject matter and iconography reveals much about the motives of those who collaborated to publish them, sometimes making them as much propaganda as art.

The post Prints & Propa­ganda appeared first on I Love Typography.

How to Simplify SVG Code Using Basic Shapes

Css Tricks - Thu, 09/03/2020 - 4:47am

There are different ways to work with icons, but the best solution always includes SVG, whether it’s implemented inline or linked up as an image file. That’s because they’re “drawn” in code, making them flexible, adaptable, and scalable in any context.

But when working with SVG, there’s always the chance that they contain a lot of unnecessary code. In some cases, the code for an inline SVG can be long that it makes a document longer to scroll, uncomfortable to work with, and, yes, a little bit heavier than it needs to be.

We can work around this reusing chunks of code with the <use> element or apply native variables to manage our SVG styles from one place. Or, if we’re working in a server-side environment, we can always sprinkle in a little PHP (or the like) to extract the contents of the SVG file instead of dropping it straight in.

That’s all fine, but wouldn’t be great if we could solve this at the file level instead of resorting to code-based approaches? I want to focus on a different perspective: how to make the same figures with less code using basic shapes. This way, we get the benefits of smaller, controllable, and semantic icons in our projects without sacrificing quality or visual changes. I’ll go through different examples that explore the code of commonly used icons and how we can redraw them using some of the easiest SVG shapes we can make.

Here are the icons we’ll be working on:

Let’s look at the basic shapes we can use to make these that keep the code small and simple.

Psssst! Here is a longer list of simple icons I created on! After this article, you’ll know how to modify them and make them your own.

Simplifying a close icon with the <line> element

This is the code for the “close” or “cross” icon that was downloaded from and built by pixel-perfect:

CodePen Embed Fallback

In this example, everything is happening inside the <path> with lots of commands and parameters in the data attribute (d). What this SVG is doing is tracing the shape from its borders.

A quick demonstration using

If you are familiar with Illustrator, this is the equivalent of drawing two separate lines, converting them to shape, then combining both with the pathfinder to create one compound shape.

The <path> element allows us to draw complex shapes, but in this case, we can create the same figure with two lines, while keeping the same appearance:

<svg xmlns="" viewBox="0 0 50 50" width="50" height="50" overflow="visible" stroke="black" stroke-width="10" stroke-linecap="round">    <line x1="0" y1="0" x2="50" y2="50" />    <line x1="50" y1="0" x2="0" y2="50" /> </svg>

We started by defining a viewBox that goes from 0,0 to 50,50. You can choose whatever dimensions you prefer; the SVG will always scale nicely to any width and height you define. To make things easier, in this case, I also defined an inline width and height of 50 units, which avoids extra calculations in the drawing.

To use the <line> element, we declare the coordinates of the line’s first point and the coordinates of its last point. In this specific case, we started from x=0 y=0 and ended at x=50 y=50.

Here’s how that looks in code:

<line x1="0" y1="0" x2="50" y2="50" />

The second line will start from x=50 y=0 and end at x=0 y=50:

<line x1="50" y1="0" x2="0" y2="50" />

An SVG stroke doesn’t have a color by default — that’s why we added the black value on the stroke attribute. We also gave the stroke-width attribute a width of 10 units and the stroke-linecap a round value to replicate those rounded corners of the original design. These attributes were added directly to the <svg> tag so both lines will inherit them.

<svg ... stroke="black" stroke-width="10" stroke-linecap="round" ...>

Now that the stroke is 10 units bigger that its default size of 1 unit, the line might get cropped by the viewBox. We can either move the points 10 units inside the viewBox or add overflow=visible to the styles.

The values that are equal to 0 can be removed, as 0 is the default. That means the two lines end up with two very small lines of code:

<line x2="50" y2="50" /> <line x1="50" y2="50" />

Just by changing a <path> to a <line>, not only did we make a smaller SVG file, but a more semantic and controllable chunk of code that makes any future maintenance much easier. And the visual result is exactly the same as the original.

CodePen Embed Fallback

Same cross, different code.

Simplifying a clock icon with the <circle> and <path> elements

I took this example of a clock icon created by barracuda from The Noun Project:

CodePen Embed Fallback

This shape was also drawn with a <path>, but we also have a lot of namespaces and XML instructions related to the software used and the license of the file that we can delete without affecting the SVG. Can you tell what illustration editor was used to create the icon?

Let’s recreate this one from scratch using a circle and a path with simpler commands. Again, we need to start with a viewBox, this time from 0,0 to 100,100, and with a width and height matching those units.

<svg xmlns="" viewBox="0 0 100 100" width="100" height="100" fill="none" stroke="black" stroke-width="10" stroke-linecap="round" stroke-linejoin="round"> <circle cx="50" cy="50" r="40"/> <path d="M50 25V50 H75" /> </svg>

We keep the same styles as the previous icon inside the <svg> tag. fill is black by default, so we need to explicitly give it a none value to remove it. Otherwise, the circle will have have a solid black fill, obscuring the other shapes.

To draw the <circle> we need to indicate a center point from where the radius will sit. We can achieve that with cx (center x) and cy (center y). Then r (radius) will declare how big our circle will be. In this example, the radius is slightly smaller than the viewBox, so it doesn’t get cropped when the stroke is 10 units wide.

What’s up with all those letters? Check out Chris Coyier’s illustrated guide for a primer on the SVG syntax.

We can use a <path> for the clock hands because it has some very useful and simple commands to draw. Inside the d (data) we must start with the M (move to) command followed by the coordinates from where we’ll start drawing which, in this example, is 50,25 (near the top-center of the circle). 

After the V (vertical) command, we only need one value as we can only move up or down with a negative or positive number. A positive number will go down. The same for H (horizontal) followed by a positive number, 75, that will draw toward the right. All commands are uppercase, so the numbers we choose will be points in the grid. If we decided to use lowercase (relative commands) the numbers will be the amount of units that we move in one direction and not an absolute point in the coordinate system.

CodePen Embed Fallback

Same clock, different code.

Simplifying an envelope icon with the <rect> and <polyline> elements

I drew the envelope icon in Illustrator without expanding the original shapes. Here’s the code that came from the export:

CodePen Embed Fallback

Illustrator offers some SVG options to export the graphic. I chose “Style Elements” in the “CSS Properties” dropdown so I can have a <style> tag that contains classes that I might want to move to a CSS file. But there are different ways to apply the styles in SVG, of course.

We already have basic shapes in this code! I unselected the “Shape to paths” option in Illustrator which helped a lot there. We can optimize this further with SVGOMG to remove the comments, XML instructions, and unnecessary data, like empty elements. From there, we can manually remove other extras, if we need to.

We already have something a little more concise:

<svg version="1.1" id="Layer_1" xmlns="" x="0" y="0" viewBox="0 0 310 190" xml:space="preserve">   <style>.st0{fill:none;stroke:#000;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}   </style><rect x="5" y="5" class="st0" width="300" height="180"/>   <polyline class="st0" points="5 5 155 110 305 5"/> </svg>

We can remove even more stuff without affecting the visual appearance of the envelope, including: 

  • version="1.1" (this has been deprecated since SVG 2)
  • id="Layer_1" (this has no meaning or use)
  • x="0" (this is a default value)
  • y="0" (this is a default value)
  • xml:space="preserve" (this has been deprecated since SVG 2)
<svg xmlns="" x="0" y="0" viewBox="0 0 310 190">   <style>.st0{fill:none;stroke:#000;stroke-width:10;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10}   </style>   <rect x="5" y="5" class="st0" width="300" height="180"/>   <polyline class="st0" points="5 5 155 110 305 5"/> </svg>

We can move the CSS styles to a separate stylesheet if we really want to get really aggressive.

<rect> needs a starting point from where we’ll extend a width and a height, so let’s use  x="5" and y="5" which is our top-left point. From there, we will create a rectangle that is 300 units wide with a height of 180 units. Just like the clock icon, we’ll use 5,5 as the starting point because we have a 10-unit stroke that will get cropped if the coordinates were located at 0,0.

<polyline> is similar to <line>, but with an infinite amount of points that we define, like pairs of coordinates, one after the other, inside the points attribute, where the first number in the pair will represent x and the second will be y. It’s easier to read the sequence with commas, but those can be replaced with whitespace without having an impact on the result.

CodePen Embed Fallback

Same envelope, different code.

Bonus shapes!

I didn’t include examples of icons that can be simplified with <polygon> and <ellipse> shapes, but here is a quick way to use them.

<polygon> is the same as <polyline>, only this element will always define a closed shape. Here’s an example that comes straight from MDN:

CodePen Embed Fallback

Remember the circle we drew earlier for the clock icon? Replace the r (radius) with rx and ry. Now you have two different values for radius. Here’s another example from MDN:

CodePen Embed Fallback Wrapping up

We covered a lot here in a short amount of time! While we used examples to demonstrates the process of optimizing SVGs, here’s what I hope you walk away with from this post:

  • Remember that compression starts with how the SVG is drawn in illustration software.
  • Use available tools, like SVOMG, to compress SVG.
  • Remove unnecessary metadata by hand, if necessary.
  • Replace complex paths with basic shapes.
  • <use> is a great way to “inline” SVG as well as for establishing your own library of reusable icons.
How many icons can be created by combining these basic shapes? 

I’m working my list on, I’ll be constantly uploading more icons and features here, and now you know how to easily modified them just by changing a few numbers. Go ahead and make them yours!

The post How to Simplify SVG Code Using Basic Shapes appeared first on CSS-Tricks.

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

Using @property for CSS Custom Properties

Css Tricks - Wed, 09/02/2020 - 12:22pm

Una Kravetz digs into how Chrome now allows you to declare CSS custom properties directly from CSS with more information than just a string.

So rather than something like this:

html { --stop: 50%; }

…can be declared with more details like this:

@property --stop { syntax: "<percentage>"; initial-value: 50%; inherits: false; }

The browser then knows this specific custom property is a percentage rather than a string. It can be other useful stuff like <integer> and <color>. Now that we have a way to communicate this sort of information to the browser, we get some new abilities, like being able to transition between two values.

While playing around, I noticed you have to very specifically call out the property to be transitioned (because a catch-all transition won’t do it). Try hovering on this demo, which is a re-creation of what Una did in the post:

CodePen Embed Fallback

Note that I’m animating the color stop’s position (which is a percentage), but I’m also trying to animate the color, which still does not work. I assumed it would with this new feature. I know people have been confused about the lack of being able to animate gradients for a long time. (See Ana Tudor’s article.)

You can always re-declare the properties somewhere at a high-level to “support” browsers that can’t read custom properties. Feels like a funny time to be talking about that. Safari seems to signal strong interest in this Houdini-based stuff, but hasn’t yet. Firefox? Eeesh, I dunno. Best we know is they labeled it as “Worth Prototyping” before all the layoffs.

This will also help with a the weird fallback issue with CSS custom properties that we mentioned in the newsletter:

As with any other custom property, you can get (using var) or set (write/rewrite) values, but with Houdini custom properties, if you set a falsey value when overriding it, the CSS rendering engine will send the initial value (its fallback value) instead of ignoring the line.

The post Using @property for CSS Custom Properties appeared first on CSS-Tricks.

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

Excluding Emojis From Transparent Text Clipping

Css Tricks - Wed, 09/02/2020 - 8:22am

CSS-Tricks has this pretty cool way of styling hovered links. By default, the text is a fairly common blue. But hover of the links, and they’re filled with a linear gradient.


Pretty neat, right? And the trick isn’t all that complicated. On hover…

  • give the link a linear gradient background,
  • clip the background to the text, and
  • give the text a transparent fill so the background shows through.

It looks like this in CSS:

a { color: #007db5; } a:hover { background: linear-gradient(90deg,#ff8a00,#e52e71); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }

Notice the -webkit- prefix, which is required for now. There’s a little more to the actual implementation here on CSS-Tricks, but this little bit gets us what we’re looking for.

CodePen Embed Fallback

But that’s not the point here. Just the other day, Brad Westfall phoned in to let us know that this technique also takes effect on emojis which, like any other text, gets a transparent fill on hover.

CodePen Embed Fallback

He noticed it happening on a link in one of our posts.

Not the worst thing. And it totally makes sense. I mean, an emoji is a glyph like any other text in a font file, right? They just happen to be a color font and take on the form of an image. Of course they would be treated like any other glyph in a situation like this where we’re hallowing out the fill color.

But if keeping the color in tact on emojis is a requirement, that can be resolved by wrapping the emoji in a span and setting its fill back to its initial state.

CodePen Embed Fallback

But who wants to write a span every time an emoji happens to pop up in a link? &#x1f44e;

If you’re looking for a CSS solution, we’re kinda out of luck. That said, the CSS Fonts Module Level 4 specification includes a definition for a proposed font-variation-emoji property. However, there’s not much on it (that I can find) at the moment and it doesn’t appear to be designed for this sort of thing, A quick skim of some discussion related to the proposal suggests it’s more about the way some browsers or systems automatically convert Unicode to emoji and how to control that behavior.

There’s also the proposed definition of font-palette in the same draft spec which seems like a way to control color fonts — that’s what emojis are at the end of the day. But this isn’t the solution, either.

It seems the only way to prevent an emoji’s fill from being changed without a span is some sort of JavaScript solution. Look at services like WordPress, Dropbox, Facebook and Twitter. They all implement their own custom emoji sets. And what do they use? Images.

Yeah, along with a lot of divs and such!

That would be one way to do it. If the emoji is replaced with an image (an SVG in this specific example), then that would certainly exclude it from being filled along with the link text.

CodePen Embed Fallback

Or, hey, why not prevent ourselves from getting into the situation at all and place that dang thing outside of the link?

CodePen Embed Fallback

That’s probably the route we should have taken all along. But an emoji might not come at the beginning or end of a link, but somewhere in the middle. It just underscores the point that there are cases where having some sort of control here could come in handy.

The post Excluding Emojis From Transparent Text Clipping appeared first on CSS-Tricks.

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

Comparing Browsers for Responsive Design

Css Tricks - Tue, 09/01/2020 - 11:14am

There are a number of these desktop apps where the goal is showing your site at different dimensions all at the same time. So you can, for example, be writing CSS and making sure it’s working across all the viewports in a single glance.

They are all very similar. For example, they do “event mirroring” meaning if you scroll in one window or device, then all the others do too, along with clicks, typing, etc. You can also zoom in and out to see many devices at once, just scaled down. Let’s see if we can root out any differences.

  • Windows, Mac, and Linux
  • “Solo” plan starts at $5/month and they have plans up from there

There are loads of little cool developer-focused features like:

  • Kill a port just by typing in the port number.
  • There’s a universal inspect mode but, while you can’t apply a change in DevTools that affects all windows and devices at the same time, you can at least inspect across all of them, and when you click, it activates the correct DevTools session.
  • Throttle or go offline in a click.
  • Turn off JavaScript with a click.
  • Turn on Design Mode with a click (e.g. every element has contenteditable).
  • Toggles for hiding images, turning off all styles, outlining all elements, etc.
  • Override fonts with Google Font choices.
Responsively App
  • Universal inspect mode that selects the correct DevTools context
  • The option to “Disable SSL Validation” is clever, should you run into issues with local HTTPS.
  • One-click dark mode toggle
  • Window and Mac
  • Free, with premium upgrades ($10/month). Some of the features like scroll syncing and auto refreshing are listed as premium features, which makes me thing that the free version limits them in some way.
  • Autorefresh is a neat idea. You set up a “watcher” for certain file types in certain folders, and if they change, it refreshes the page. I imagine most dev environments have some kind of style injection or hot module reloading, but having it available anyway is useful for ones that don’t.
  • There is no universal DevTools inspector, but you can open the DevTools individually and they do have a custom universal inspection tool for showing the box model dimensions of elements.
  • There’s a custom error report screen.
  • You can enable “Browsing Mode” to turn off all the fancy device stuff and just use it as a semi-regular browser.
  • Windows, Mac, and Linux
  • Free, with premium plans starting at $10/month. Signing up is going to get you a good handful onboarding emails over a week (with the option to you can opt out).
  • It has browser extensions for other browsers to pop your current tab over to Polypane
  • The universal inspect mode seems the most seamless of the bunch to me, but it doesn’t go so far propagate changes across windows and devices. Someone needs to do this! It’s does have a “Live CSS” pane that will inject additional CSS to all the open devices though, which is cool.
  • It can open devices based on breakpoints in your own CSS — and it actually works!
  • It’s on the Mac App Store for $5, but its website is offline, which makes it seem kinda dead.
  • It has zero fancy features. As the name implies, it simply shows the same site side-by-side in two columns that can be resized.
  • It’s not a separate browser app, but a browser extension. I kind of like this as I can stay in a canonical browser that I’m already comfortable with that’s getting regular updates.
  • The “breakpoints” view is a clever idea. I believe it should show your site at the breakpoints in your CSS, but, it seems broken to me. I’m not sure if this is an actively developed project. (My guess is that it is not.)

What, you want me to pick a winner?

While I was turned off a little Polypane’s hoop jumping and onboarding, I think it has the most well-considered feature set. Sizzy is close, but the interface is more cluttered in a way that doesn’t seem necessary. I admit I like how Blisk is really focused on “just look at the mobile view and then we’ll fill the rest of the space with a larger view” because that’s closer to how I actually work. (I rarely need to see a “device wall” of trivially different mobile screens.)

The fact that Responsively is free and open source is very cool, but is that sustainable? I think I feel safer digging into apps that are run as a business. The fact that I just stay in my normal browser with Re:View means I actually have the highest chance of actually using it, but it feels like a dead project at the moment so I probably won’t. So, for now, I guess I’ll have to crown Polypane.

The post Comparing Browsers for Responsive Design appeared first on CSS-Tricks.

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

Come to Web Unleashed!

Css Tricks - Tue, 09/01/2020 - 4:28am

(This is a sponsored post.)

Web Unleashed is a fun conference. I’ve been a number of times. I’m sure you won’t be surprised that it’s online this year, like most events.

And, hey, it’s coming up and will take place over three days, October 5-7, 2020. I’d really like to see you there, not just because you’re going to get a lot of it (which you will), but because I’ll be there emceeing the show on October 5th, right after Jason Pamental does the opening. I’m also interviewing Mina Markham which is sure to be both fun and interesting.

But you can expect much, much more over the three days that Web Unleashed takes place. I mean, just look at the lineup.

Tickets are $249 Canadian. If you’re looking for a discount, I’ve got one right here that will knock $100 off the registration. Use coupon code CSS-Tricks when registering for the event to get the special price. Just make sure you do it soon because it’s only valid until September 10. And, yes, group discounts are also available. I’m gonna say that again but bigger:

Use coupon CSS-Tricks because it’s literally 40% off the already-affordable ticket price, but you have to do it before September 10, 2020.

Oh, and one more thing! Check out the artwork for the event:

It’s beautiful, right? That was done by Matt Deslauriers and was the inspiration behind a little tool I put together that creates random generative art that can be exported as SVG and PNG. I told you his was way cooler.

Direct Link to ArticlePermalink

The post Come to Web Unleashed! appeared first on CSS-Tricks.

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

Syndicate content
©2003 - Present Akamai Design & Development.