Web Standards

Editing HTML Like A Boss In VS Code

Css Tricks - Wed, 09/16/2020 - 4:50am

Here’s a seven minute video from Caleb Porzio that focuses on some of Emmet‘s HTML editing features. You might think of Emmet as that thing that expands abbreviations like table.stats>tr*3>td*3 into glorious, expanded, and perfect HTML. But Emmet has other HTML editing trickery up its sleeve. My favorite is “wrap with abbreviation” (which happens to be Cmd/Ctrl + Shift + A on CodePen), but there are more, like expanding your selection inward and outward and tag changing.

If you haven’t seen it, the Emmet 2 preview on CodePen is pretty neeeeat. It shows you what you’re about to expand into before you do it:

Direct Link to ArticlePermalink

The post Editing HTML Like A Boss In VS Code appeared first on CSS-Tricks.

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

What is the Value of Browser Diversity?

Css Tricks - Tue, 09/15/2020 - 9:36am

In 2018, Rachel Nabors made the point that browser diversity is similar to biological ecosystem diversity. There are literal advantages to more diversity. That article was before the Edge engines were shut, and now the big shakeups at Mozilla have the topic of browser diversity on people’s minds again.

I really like Dave’s take on the matter. The diversity of browser engines makes web tech slow. Frustratingly slow, to many, but that slowness can bring value.

There’s a lot of value in slow thinking. You use the non-lizard side of your brain. You make more deliberate decisions. You prioritize design over instant gratification. You can check your gut instincts and validate your hypothesis before incurring mountains of technical debt.

I’d bet you a dollar that the less engines we have, the faster things get. Fast can be satisfying in the moment, but doesn’t make for the best brisket.

If we do see a major reduction in browser diversity, I think we lose the intentional slowness and the cooperation mechanisms we have in place. Who knows what will happen, but my hope is that just like iron can sharpen iron, maybe chromium can sharpen chromium.

Direct Link to ArticlePermalink

The post What is the Value of Browser Diversity? appeared first on CSS-Tricks.

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

Virtual Event Registrations with Wufoo Forms

Css Tricks - Tue, 09/15/2020 - 5:10am

(This is a sponsored post.)

We’ve seen many events shift from in-person to online this year. That may have required a huge change to how you collect attendee registrations in the past, but with a paid Wufoo account and Zoom — along with a sprinkle of Zapier — it’s easier than ever to go virtual.

First, set up a Zoom call

It doesn’t have to start right now but can be scheduled in advance so we have something to connect to. In Zoom, that’s just a click of the giants “Schedule” button on the welcome screen once the app has been launched.

“New Meeting” will launch something right away, whereas “Schedule” will set a call up in advance to start at a fitter date and time. Next, we need a registration form

We’re talking about Wufoo’s bread and butter: making online forms! We can create one from scratch, of course, but Wufoo makes it even easier with a set of pre-made options that are specifically designed for registration.

Any of these can be used as-is, or as a starting point to make your own.

Whether you start with a clean slate or a template, the key things you’re going to want to collect are:

  • Name
  • Email address

Seriously, that’s it. Anything else is icing on the cake that can be used to collect additional information about attendees, like their age, gender, shirt size, allergies, or whatever else you think will be helpful to make a better event.

Is this a paid event?

Many events are! If you want to charge a fee for the event, Wufoo integrates with Stripe, Square, PayPal and a slew of other payment gateways that make collecting payments rather trivial. Plus, transactions are protected by 256-bit SSL encryption that’s super secure and PCI-compliant.

Purchasing a single ticket is pretty straightforward, but let’s say you want to allow folks to purchase multiple tickets at a time or have multiple tiers of ticket pricing. Not a problem at all in Wufoo! For example, it’s possible to set prices by the answer provided in a field.

Now, when someone selects an option in the “Number of Tickets” field, a price will calculated. Is there a maximum number of “seats” available?

You may be cool with an unlimited number of attendees. But if you need to limit the head count, check out Wufoo’s Max Quantity feature, which is like creating a pool of tickets that each registration subtracts from. This is especially useful to create a more “intimate” presentation for, say, workshops or group activities.

The “Max Quantities” feature can restrict the number of people who can register for a specific workshop. Connect to Zoom

We’re using Zoom in this example, but Wufoo is capable of connecting to other video services, including join.me, GoToMeeting, and Cisco Webex.

Wufoo’s integrations come by way of Zapier. If you’re new to it, Zapier is this thing that basically connects apps together, establishing communication between their APIs so that they interact with each other when something happens. In this case, when someone signs up for the virtual event, we want to add them as a guest on the Zoom call.

So, go into your Zapier account (or set one up for free). From there, we’ll create a new “zap” which Zapier’s slang for a new app connection. That means we select Wufoo as the first app we want to use and Zoom as the app we want to connect to.

Once the apps have been chosen, Zapier provides options for what to “watch for” in Wufoo (a form submission, or “New Entry” in this case) and actions we want to take place in Zoom when that trigger happens (“Create Webinar Registrant” in this case).

Click the “Use Zap” button and Zapier will walk through the rest of the steps, including what form to use in this integration and which scheduled Zoom webinar to create registrants.

Watch the registrations roll in!

Well, yes. We are technically done at this point, but we’ll want to do some housecleaning before we can actually start collecting registrations:

  • Finish designing the form. Wufoo has a lot of nice design options, and even takes custom CSS to fine-tune the way things look.
  • Embed the form. The form needs to go somewhere if we want folks to use it. A Wufoo form can be embedded just about anywhere (hey, we use on on our own Contact page). Or, simply link it up and use the public URL Wufoo generates for the form.
  • Customize the receipt email. Once a transaction is made, the user will get a receipt emailed to their inbox. It’s a good idea to give it a little love so it’s personalized.
  • Create a reminder email. Sending a reminder a few days before the event is a nice way to give folks a heads up that the event is coming up. Wufoo also integrates with both Mailchimp and Campaign Monitor, both of which can be used in a zap that adds attendees to an email list and sends triggered and automated messages.

There you go, a registration flow for a virtual event that is powerful and doesn’t require any code! If you don’t have a Wufoo account already, get one now — it’s free and worth exploring all the interesting things it can do.

Direct Link to ArticlePermalink

The post Virtual Event Registrations with Wufoo Forms appeared first on CSS-Tricks.

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

Form design

Css Tricks - Tue, 09/15/2020 - 5:04am

A very digestable guide from Geri Reid on building forms. Not the code, but the design and UX principles that should guide the code.

Working on a design system for a bank has taught [me] a lot about forms. I’ve watched testing in our labs. I’ve worked alongside experts from specialist accessibility organisations. I’ve seen forms tested by disabled people and users of assistive technology. I’ve also read a lot of research.

From all this learning I’ve formed my own forms best-practice guidelines. 

I always think about one code-related thing when it comes to general form advice: all inputs need an attached label.

<label for="name">Name:</label> <input type="text" id="name" name="name"> <!-- or --> <label> Name: <input type="text" name="name"> </label>

It’s HTML 101 stuff, but so many forms fail to do it. I once heard a story about blind college-bound high school students who were unable to apply to college specifically because they couldn’t figure out what the inputs wanted on a form. They started second-guessing if they could do college on their own after that experience.

You know how The Onion prints the article “‘No Way To Prevent This,’ Says Only Nation Where This Regularly Happens” literally every single time there is a mass shooting? I feel like someone should make a website that publishes an article pointing to every single website that fails this one test with a headline like “‘No Way To Prevent This’, Says Website Where The Fix Would Be Typing A Handful Of Characters.”

Direct Link to ArticlePermalink

The post Form design appeared first on CSS-Tricks.

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

Winamp Skin Museum

Css Tricks - Mon, 09/14/2020 - 1:42pm

65,000 skins, they say. That’s extraordinary, especially considering how creative and well done many of them are. MySpace was an even bigger creative explosion of customization.

What’s the next product that will inspire this kind of user ownership through theming? Allowing it isn’t terribly difficult. You allow people to write (or link up) their own CSS and, ideally, give them sensible selectors to hook onto.

Be careful you don’t open up any XSS holes. The much harder trick is building something that people want to skin. Once you’re over that hump, it’s about having enough people theming it that it starts to inspire other people to do the same.

Direct Link to ArticlePermalink

The post Winamp Skin Museum appeared first on CSS-Tricks.

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

content-visibility: the new CSS property that boosts your rendering performance

Css Tricks - Mon, 09/14/2020 - 11:28am

Una Kravets and Vladimir Levin:

[…] you can use another CSS property called content-visibility to apply the needed containment automatically. content-visibility ensures that you get the largest performance gains the browser can provide with minimal effort from you as a developer.

The content-visibility property accepts several values, but auto is the one that provides immediate performance improvements.

The perf benefits seems pretty big:

In our example, we see a boost from a 232ms rendering time to a 30ms rendering time. That’s a 7x performance boost.

It’s manual work though. You have to “section” large vertical chunks of the page yourself, apply content-visibility: auto; to them, then take a stab at about how tall they are, something like contain-intrinsic-size: 1000px;. That part seems super weird to me. Just guess at a height? What if I’m wrong? Can I hurt performance? Can (or should) I change that value at different viewports if the height difference between small and large screens is drastic?

Seems like you’d have to be a pretty skilled perf nerd to get this right, and know how to look at and compare rendering profiles in DevTools. All the more proof that web perf is its own vocation.

Direct Link to ArticlePermalink

The post content-visibility: the new CSS property that boosts your rendering performance appeared first on CSS-Tricks.

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

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('https://fonts.googleapis.com/css2?family=Montserrat:wght@300'); 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!

Install Ant.design 

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.

Ant.design 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 "run.sh" write text "cd '/Users/chriscoyier/GitHub/CPOR'" write text "./run.sh" 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("https://cdn.jsdelivr.net/gh/reworkcss/css@latest/lib/parse/index.js").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.

Syndicate content
©2003 - Present Akamai Design & Development.