Front End Web Development

Add a CSS Lens Flare to Photos for a Bright Touch

Css Tricks - Tue, 04/12/2022 - 7:10am

I’m a big fan of movies by J.J. Abrams. I enjoy their tight plots, quippy dialog, and of course: anamorphic lens flares. Filmmakers like Abrams use lens flare to add a dash of ‘homemade’ realism to their movies, a technique we can easily recreate in tools like Photoshop, then add to our sites as raster images.

But what if we wanted to apply the same lens flare look without the use of photo editing tools? We can create a CSS lens flare to add a cinematic touch to our gallery images, background photos, or user profiles.

There are different types of flares in photography. The one we’re working with is known as artifacts, as they leave behind little blotches of light that take the shape of a camera’s aperture where the light enters and reflects off the surface of the lens.

Source: Wikipedia

Here’s a good example of the sort of lens flare we’re going to make, pulled straight from a J.J. Abrams movie still, naturally:

Star Trek (2009)

There are a few parts to the lens flare above. Let’s list them out so we know what we’re aiming for:

  1. The center light source appears as a glowing ball of light.
  2. There are some horizontal elliptical light streaks — rays of light that are distorted and blurred, resulting in elongated ellipses.
  3. Random rays of light shoot off from the center light source at various angles.

We start with the HTML elements below that map to our flare components. There is a central light source and two off-diagonal circular flares, three horizontal lens flares, and three conical ray-like flares.

<div class="lens-center"></div> <div class="circle-1"></div> <div class="circle-2"></div> <div class="left-flare horizontal-flare"></div> <div class="right-flare horizontal-flare"></div> <div class="full-flare horizontal-flare"></div> <div class="conic-1"></div> <div class="conic-2"></div> <div class="conic-3"></div> </div>

Lastly, in order for our lens flare to be believably superimposed on an image, its center light source has to be adjustable. This way, we can place it over a believable existing light source on a picture and not overlap with any faces.

The background and light source of a CSS lens flare

Let’s start with a black background and central light source for our CSS lens flare. Most gradients on the web are linear gradients with solid-color transitions, but we can apply alpha channels to them which is actually a nice way to produce a glowing effect. A circular-shaped radial gradient with multiple layers of semi-transparent colors gives us a good camera center effect.

background: radial-gradient( closest-side circle at center, hsl(4 5% 100% / 100%) 0%, hsl(4 5% 100% / 100%) 15%, hsl(4 10% 70% / 70%) 30%, hsl(4 0% 50% / 30%) 55%, hsl(4 0% 10% / 5%) 75%, transparent 99 ); filter: blur(4px);

Curious about that HSL syntax? It’s new and appears to be the future direction of defining alpha transparency in all CSS color functions.

Notice we’re using a CSS blur filter in there to make the gradients look a bit closer to layers of diffused light.

Now that we know how to add circular flares, we will also add a larger, diffused flare behind the light source, as well as three additional flares at a 45deg angle from the center, to give the effect a more realistic look.

CodePen Embed Fallback Setting up horizontal light streaks

Let’s start with horizontal flares. There are a few options we can take, a very elongated ellipse gradient would be the simplest approach. However, I’ve noticed that horizontal lens flares are usually less symmetrical than the ones in my reference photos, so I wanted to make mine a little less symmetrical as well.

Luckily, radial gradients have an optional location argument in CSS. We can create two slightly differently-sized left and right portions of the same horizontal flare, and with slightly different colors. We can also add an opacity filter to make the area where the horizontal flares join the center to make the flare less jarring.

background: radial-gradient( closest-side circle at center, transparent 50%, hsl(4 10% 70% / 40%) 90%, transparent 100% ); filter: blur(5px);

While we are at it, let’s also add a single full elongated elliptical bottom flare three-quarters of the way down the viewport for another touch of “realism.”

CodePen Embed Fallback Creating the diffused rays of light

With both the radial and horizontal flares in place, all we have left are the angled rays of light shooting off from the light source. We could add additional elliptical radial gradients then skew and translate the container to get a close approximation. But we also have a CSS gradient that’s already made for the job, the conic gradient. Below is an example that gives us a 7deg conic gradient at a 5deg offset from its container’s bottom-right corner.

background: conic-gradient( from 5deg at 0% 100%, transparent 0deg, hsl(4 10% 70% / 30%) 7deg, transparent 15deg ); transform-origin: bottom left; transform: rotate(-45deg);

We’ll add a few conic gradients centered at our flare center, with various gradient angles of semi-transparent colors. Because conic gradients can show the corner of its container div, we will rotationally transform them using our light source as its origin, resulting in an offset diffused ray filter effect.

CodePen Embed Fallback Using CSS custom properties for a more flexible lens flare

So far, we’ve created a responsive, but statically-positioned, lens flare effect at a fixed location. It would be difficult to adjust the center of the lens flare without also breaking the horizontal and conic flares around it.

To make the CSS lens flare both adjustable and less brittle, we’ll expose the light source flare’s position, size, and hue via a set of custom properties.

:root { --hue: 4; --lens-center-size: 40%; --lens-spread-size: 80%; --lens-left: 55%; --lens-top: 15%; }

While we are at it, we are also going to adjust the flare hue and the size of the horizontal flare height. For horizontal flare width, we use CSS variable overloading to make them adjustable on their own; otherwise, we fall back to the light source flare center or the image center.

.left-flare { width: var(--left-flare-width, var(--lens-left, 50%)); }

This is what the completed CSS lens flare effect looks like with a photo background and the lens flare moved up so the light source location looks believable. Go ahead, add your own photo to see how it works in different contexts!

CodePen Embed Fallback Other CSS and non-CSS lens flare examples

This is just one way to create a CSS lens flare, of course. I like this approach because it’s flexible in terms of the color, size, and positioning of the flare and its parts. That makes it more of a reusable component that can be used in many contexts.

Here’s one by Keith Grant that uses a linear gradient as well as CSS custom properties. Then it sprinkles some JavaScript in there to randomize the HSLA values.

CodePen Embed Fallback

Nicholas Guest has another CSS lens flare that applies a box shadow on the ::before and ::after pseudo-elements of a .flare element to get the effect, plus a smidge of jQuery that makes the flare follow the mouse on hover.

CodePen Embed Fallback

This one is made with Canvas and is neat in how the light source follows the mouse on hover while showing how the lens flare artifacts change position as the light source position changes.

CodePen Embed Fallback

The same sort of idea here:

CodePen Embed Fallback

And a fun one that uses GSAP, Canvas, and a library called JS.LensFlare:

CodePen Embed Fallback

How would you approach a CSS lens flare effect? Share in the comments!

Add a CSS Lens Flare to Photos for a Bright Touch originally published on CSS-Tricks. You should get the newsletter.

Bodoni Egyptian Mono

Typography - Fri, 04/08/2022 - 1:00am

Read the book, Typographic Firsts

In a landscape filled with thousands of typefaces, Bodoni Egyptian Mono is an unexpected design that mixes together wildly divergent DNAs. We interviewed its designer, Nick Shinn of Shinntype.

The post Bodoni Egyptian Mono appeared first on I Love Typography.

Schotis Display font family

Typography - Thu, 04/07/2022 - 12:00am

Read the book, Typographic Firsts

Schotis Display is the companion to Schotis Text and is meant to be used in headlines, in subheadings, and other large size settings. Its design is inspired by 19th-century Scotch Romans, but has a thoroughly contemporary look.

The post Schotis Display font family appeared first on I Love Typography.

Layfort font family

Typography - Tue, 04/05/2022 - 9:00pm

Read the book, Typographic Firsts

The brand new Layfort font family takes its inspiration from Art Deco typefaces and crosses that with a dash of industrial flavor to arrive at a distinct typographic voice. It feels fashionable but without frills, relaxed in a luxurious rhythm but with a serious undertone.

The post Layfort font family appeared first on I Love Typography.

Steven Heller’s Font of the Month: Boucan

Typography - Tue, 04/05/2022 - 4:59am

Read the book, Typographic Firsts

Join Steven Heller for this special episode of Font of the Month as he takes a closer look at the brand new Boucan, an innovative, playful, and brilliant new font family from Malou Verlomme.

The post Steven Heller’s Font of the Month: Boucan appeared first on I Love Typography.

Adding CDN Caching to a Vite Build

Css Tricks - Mon, 04/04/2022 - 8:25am

Content delivery networks, or CDNs, allow you to improve the delivery of your website’s static resources, most notably, with CDN caching. They do this by serving your content from edge locations, which are located all over the world. When a user browses to your site, and your site requests resources from the CDN, the CDN will route that request to the nearest edge location. If that location has the requested resources, either from that user’s prior visit, or from another person, then the content will be served from cache. If not, the CDN will request the content from your underlying domain, cache it, and serve it.

There are countless CDNs out there, but for this post we’ll be using AWS CloudFront. We’ll look at setting up a CloudFront distribution to serve all our site’s assets: JavaScript files, CSS files, font files, etc. Then we’ll see about integrating it into a Vite build. If you’d like to learn more about Vite, I have an introduction here.

Setting up a CloudFront CDN distribution

Let’s jump right in and set up our CloudFront CDN distribution.

For any serious project, you should be setting up your serverless infrastructure with code, using something like the Serverless Framework, or AWS’s CDK. But to keep things simple, here, we’ll set up our CDN using the AWS console.

Head on over to the CloudFront homepage. At the top right, you should see an orange button to create a new distribution.

The creation screen has a ton of options, but for the most part the default selections will be fine. First and foremost, add the domain where your resources are located.

Next, scroll down and find the Response headers policy dropdown, and choose “CORS-With-Preflight.”

Lastly, click the Create Distribution button at the bottom, and hopefully you’ll see your new distribution.

Integrating the CDN with Vite

It’s one thing for our CDN to be set up and ready to serve our files. But it’s another for our site to actually know how to request them from our CDN. I’ll walk through integrating with Vite, but other build systems, like webpack or Rollup, will be similar.

When Vite builds our site, it maintains a “graph” of all the JavaScript and CSS files that various parts of our site import, and it injects the appropriate <script> tags, <link> tags, or import() statements to load what’s needed. What we need to do is tell Vite to request these assets from our CDN when in production. Let’s see how.

Open up your vite.config.ts file. First, we’ll need to know if we’re on the live site (production) or in development (dev).

const isProduction = process.env.NODE_ENV === "production";

This works since Vite sets this environment variable when we run vite build, which is what we do for production, as opposed to dev mode with hot module reloading.

Next we tell Vite to draw our assets from our CDN like so, setting the base property of our config object:

export default defineConfig({ base: isProduction ? process.env.REACT_CDN : "",

Be sure to set your REACT_CDN environment variable to your CDN’s location, which in this case, will be our CloudFront distribution’s location. Mine looks something (but not exactly) like this:

https://distributiondomainname.cloudfront.net Watch your VitePWA settings!

As one final piece of cleanup, if you happen to be using the VitePWA plugin, be sure to reset your base property like this:

VitePWA({ base: "/",

Otherwise, your web.manifest file will have invalid settings and cause errors.

Let’s see the CDN work

Once you’re all set up, browse to your site, and inspect any of the network requests for your script or CSS files. For starters, the protocol should be h2.

From there, you can peek into the response headers of any one of those files, and you should see some CloudFront data in there:

Cache busting

It’s hard to talk about CDNs without mentioning cache busting. CDNs like CloudFront have functionality to manually “eject” items from cache. But for Vite-built assets, we get this “for free” since Vite adds fingerprinting, or hash codes, to the filenames of the assets it produces.

So Vite might turn a home.js file into home-abc123.js during a build, but then if you change that file and rebuild, it might become home-xyz987.js. That’s good, as it will “break the cache,” and the newly built file will not be cached, so the CDN will have to turn to our host domain for the actual content.

CDN caching for other static assets

JavaScript, CSS, and font files aren’t the only kinds of assets that can benefit from CDN caching. If you have an S3 bucket you’re serving images out of, consider setting up a CloudFront distribution for it as well. There are options specifically for S3 which makes it a snap to create. Not only will you get the same edge caching, but HTTP/2 responses, which S3 does not provide.

Advanced CDN practices

Integrating a CDN here was reasonably straightforward, but we’re only enjoying a fraction of the potential benefits. Right now, users will browse to our app, our server will serve our root HTML file, and then the user’s browser will connect to our CDN to start pulling down all our static assets.

Going further, we would want to serve our entire site from a CDN. That way, it can communicate with our web server as needed for non-static and non-cached assets.

Conclusion

CDNs are a great way to improve the performance of your site. They provide edge caching and HTTP/2 out of the box. Not only that, but they’re reasonably easy to set up. Now you have a new tool in your belt to both set up a CDN and integrate it with Vite.

Adding CDN Caching to a Vite Build originally published on CSS-Tricks. You should get the newsletter.

Tricks to Cut Corners Using CSS Mask and Clip-Path Properties

Css Tricks - Wed, 03/30/2022 - 6:35am

We recently covered creating fancy borders with CSS mask properties, and now we are going to cut the corners with CSS mask and clip-path! A lot of techniques exist to cut different shapes from the corners of any element. In this article, we will consider modern techniques to create unique corner shapes while trying to work from reusable code that allows us to produce different results by adjusting variables.

Check this online tool to get an idea of what we are building. It’s a CSS generator where you select the shape, the corners, and the size then you get the code in no time!

We mainly have two types of cuts: a circular one and an angled one. For each, we can get the full shape or the border-only shape, not to mention that we can select the corners we want to cut. A lot of combinations!

Like in the previous article, we will make lots of use of the CSS mask property. So, if you are not familiar with it, I recommend reading the quick primer I wrote before continuing.

Circular cut-out

For a circular or rounded cut, we will use radial-gradient(). To cut four corners, the logical solution is to create four gradients, one for each corner:

CodePen Embed Fallback

Each gradient is taking a quarter of the element’s dimensions. The syntax of the gradient is self-explanatory:

radial-gradient(circle 30px at top left, #0000 98%, red) top left;

Translated, this renders a circle at the top-left corner with a 30px radius. The main color is transparent (#0000) and the remaining is red. The whole gradient is also placed so that it starts at the element’s top-left corner. Same logic for the three other gradients. The keyword circle can be omitted since we explicitly specified one value for the radius.

Like I did in the previous article, I will be using slightly bigger or smaller values this time around in order to avoid bad visual result. Here, I am using 98% instead of 100% to avoid jagged edges and 51% instead of 50% to create an overlap between gradients and avoid white spaces. This logic will follow throughout this article. In fact, you will find that adding or removing 1% or 1deg typically results in a nice visual.

We apply this to the CSS mask property and we are done!

CodePen Embed Fallback

We can actually optimize that code a little:

--g: #0000 98%,#000; --r: 30px; mask: radial-gradient(var(--r) at 0 0 ,var(--g)) 0 0, radial-gradient(var(--r) at 100% 0 ,var(--g)) 100% 0, radial-gradient(var(--r) at 0 100%,var(--g)) 0 100%, radial-gradient(var(--r) at 100% 100%,var(--g)) 100% 100%; mask-size: 51% 51%; mask-repeat: no-repeat;

This way, we use custom properties for the redundant values and, as a personal preference, I am using numeric values for the positions instead of keywords.

In the generator, I will use the following syntax:

--g: #0000 98%,#000; --r: 30px; mask: radial-gradient(var(--r) at 0 0 ,var(--g)) 0 0 /51% 51% no-repeat, radial-gradient(var(--r) at 100% 0 ,var(--g)) 100% 0 /51% 51% no-repeat, radial-gradient(var(--r) at 0 100%,var(--g)) 0 100%/51% 51% no-repeat, radial-gradient(var(--r) at 100% 100%,var(--g)) 100% 100%/51% 51% no-repeat;

The shorthand syntax is easier to generate plus the whole value can be used as one custom property.

Can we use fewer gradients if we want?

Sure! One gradient can do the job. Hover the below to see the trick:

CodePen Embed Fallback

Here, we define one radial-gradient() with no size (by default it is 100% height and 100% width). This gives us a hole in the center. We translate/move the gradient by half the width and height of the image to move the hole to one corner. Since, by default, the CSS mask repeats, we get the same on each corner. We have four cut corners with only one gradient!

The only drawback of this method is that we need to know the width and height of the element in advance.

Can’t we use -50% instead of half the width and height?

Unfortunately, we’re unable to do that here because percentages doesn’t behave the same as pixel values when used with the CSS mask-position property. They’re tricky.

I have a detailed Stack Overflow answer that explains the difference. It deals with background-position but the same logic applies to the CSS mask-position property.

However, we can use some tricks to make it work with percentage values and without the need to know the width or the height. When a gradient (or a background layer) has a width and height equal to the element, we cannot move it using percentage values. So we need to change its size!

I will define a size equal to 99.5% 99.5%. I am reducing 0.5% from the width and the height to have a value different from 100% and at the same time keep the same visual result since we won’t notice a big difference between 100% and 99.5%. Now that our gradient has a size different from 100% we can move it using percentage values.

I will not detail all the math, but to move it by half the width and the height we need to use this equation:

100% * (50/(100 - 99.5)) = 100% * 100 = 10000%

It’s a strange value but it does the job:

CodePen Embed Fallback

As you can see, the trick works just fine. Whatever the size of the element is, we can cut four corners using only one gradient. However, this method has a small drawback when the width or the height of the element is a decimal value. Here is an example with an image having a width equal to 150.5px:

CodePen Embed Fallback

The use of 99.5% combined with 150.5px will create rounding issues that will break the calculation, resulting in the mask being misaligned. So, use this method with caution.

To overcome the rounding issue, we can combine the last trick with a pseudo-element. Here is a step-by-step illustration to understand the idea:

CodePen Embed Fallback

Here’s what going on in there:

  1. We define a pseudo-element that behaves as our background layer. Logically, we should use inset:0 to make it cover the entire area, but we will create a small overflow by using inset: -10% meaning that the pseudo element will overflow each side by 10%.
  2. We set our CSS mask to the pseudo-element. The mask size needs to match the size of the main element, not the pseudo-element. In other words, it will be smaller than the size of the pseudo-element and this is what we want to be able to move using percentage values. After we do the math, the size needs to be 100%/1.2. Notice in the demo above that the CSS mask is within the green border so that it matches the size of the container.
  3. Now, we need to move it in a way that simulates cutting the corner of the main element. The center of the hole needs to be in the corner of the main element, as illustrated in the demo. To do this, we use mask-position: 300% 300% ( 300% = 50%/(1 - 1/1.2) ).
  4. We remove no-repeat to activate the repetition and get the same effect for every corner.
  5. We clip the overflow and we get our final result!

I know it’s a bit overkill, but it does work and it requires only one gradient instead of four.

Let’s quickly recap the three methods we just covered:

  • The first method uses four gradients and has no drawbacks as far as usage. Sure, it’s verbose but it works with any kind of element and size. I recommend using this one.
  • The second method uses one gradient and works with any element, but it can break in some particular cases. It’s suitable with fixed-size elements. It’s ok to use, but maybe less frequently.
  • The third method uses one gradient and requires a pseudo-element. It won’t work with <img> and other elements that unable to support a pseudo-element.

The generator only supports the first and third methods.

Now that we saw the case with all the corners, let’s disable some of them. Using the first method, any corner we want to keep uncut we simply remove its gradient and adjust the size of what remains.

CodePen Embed Fallback

To disable the top-right corner:

  • We remove the top-right gradient (the blue one).
  • We have an empty corner, so we increase the size of the red gradient (or the purple one) to cover that leftover space.

Done!

You probably see just how many possibilities and combinations we can do here. If we want to cut N corners (where N ranges from 1 to 4), we use N gradients. All we need is to correctly set the size of each one to leave no space.

What about the other methods where there’s only one gradient? We will need another gradient! Those two methods use only one radial-gradient() to cut the corners, so we will rely on another gradient to “hide” the cut. We can use a conic-gradient() with four sections for this task:

conic-gradient(red 25%, blue 0 50%, green 0 75%, purple 0)

We add it on the top of the radial gradient to get the following:

CodePen Embed Fallback

The conic-gradient() covers the radial-gradient() and no corner is cut. Let’s change one color in the conic-gradient() to transparent. The one at the top-right, for example:

CodePen Embed Fallback

Did you see that? We revealed one corner of the radial-gradient() and we end with one cut corner!

Now let’s do the same thing, but for the bottom-left corner.

CodePen Embed Fallback

I think you probably get the trick by now. By changing the colors of the conic-gradient() from opaque to transparent, we reveal the corners we want to cut and gain all kinds of possible combinations. The same can be done with the third method.

Circular border-only cut-out

Let’s make the border-only version of the previous shape. In other words, we achieve the same shape but knock out the fill so all we’re left with is a border of the shape.

This is a bit tricky because we have different cases with different code. Fair warning, I will be using a lot of gradients here while finding opportunities to trim the number of them.

It should be noted that we will consider a pseudo-element in this case. Showing only the border means we need to hide the inner “fill” of the shape. Applying this to the main element will also hide the content — that’s why this is a nice use case for a pseudo-element.

One cut corner

This one needs one radial gradient and two conic gradients:

CodePen Embed Fallback

The first example illustrates the radial gradient (in red) and both conic gradients (in blue and green). In the second example, we apply all of them inside the CSS mask property to create the border-only shape with one cut corner.

Here’s a diagram of the game plan.

As the diagram shows, the radial-gradient() creates the quarter of a circle and each conic-gradient() creates two perpendicular segments to cover two sides. It should be noted that overlapping gradients is not an issue since we are not going to change the CSS mask-composite property value.

Using the same code an adjusting a few variables, we can get the shape for the other corners.

Two cut corners

For the two-corner configuration we have two situations taking place.

In the first situation, there are two opposite corners where we need two radial gradients and two conic gradients.

CodePen Embed Fallback

The configuration is almost the same as cutting only one corner: we add an extra gradient and update a few variables.

In the second situation, there are two adjacent corners and, in this case, we need two radial gradients, one conic gradient, and one linear gradient.

CodePen Embed Fallback

“Wait!” you might exclaim. “How come the conic gradient covers three sides?” If you check the code, notice the repeat-y. In all of the examples, we always used no-repeat for the gradients, but for this we can repeat one of them to cover more sides and reduce the number of gradients we use.

Here is an example with only the conic-gradient() to understand the repetition. The trick is to have a height equal to 100% minus the border size so that the gradient fills that space when repeating, which covers the third side in the process.

CodePen Embed Fallback Three cut corners

For this configuration, we need three radial gradients, one conic gradient, and two linear gradients.

CodePen Embed Fallback Four corners cut

It takes four radial gradients and two linear gradients to cut all four corners.

CodePen Embed Fallback

I can hear you screaming, “How the heck am I supposed to memorize all these cases?!” You don’t need to memorize anything since you can easily generate the code for each case using the online generator. All you need is to understand the overall trick rather than each individual case. That’s why I’ve only gone into fine detail on the first configurations — the rest are merely iterations that tweak the initial foundation of the trick.

Notice there’s a general pattern we’ve been following throughout the examples:

  1. We add a radial-gradient() on the corners we want to cut.
  2. We fill the sides using either a conic-gradient() or a linear-gradient() to create the final shape.

It should be noted that we can find different ways to create the same shape. What I am showing in this post are the methods I found to be best after trying lots of other ideas. You may have a different approach you consider to be better! If so, definitely share it in the comments!

Angled cut-out

Let’s tackle another type of cut shape: the angled cut.

We have two parameters: the size and angle of the cut. To get the shape, we need a conic-gradient() for each corner. This configuration is very similar to the example that kicked off this article.

CodePen Embed Fallback

Here is an illustration of one corner to understand the trick:

The difference between each corner is an extra offset of 90deg in from and the at position. The full code is like below:

--size: 30px; --angle: 130deg; --g: #0000 var(--angle), #000 0; mask: conic-gradient(from calc(var(--angle)/-2 - 45deg) at top var(--size) left var(--size),var(--g)) top left, conic-gradient(from calc(var(--angle)/-2 + 45deg) at top var(--size) right var(--size),var(--g)) top right, conic-gradient(from calc(var(--angle)/-2 - 135deg) at bottom var(--size) left var(--size),var(--g)) bottom left, conic-gradient(from calc(var(--angle)/-2 + 135deg) at bottom var(--size) right var(--size),var(--g)) bottom right; mask-size: 51% 51%; mask-repeat: no-repeat;

If we want to disable one corner, we remove the conic-gradient() for that corner and update the size of another one to fill the remaining space exactly like we did with the circular cut. Here’s how that looks for one corner:

CodePen Embed Fallback

We can do the exact same thing for all the other corners to get the same effect.

In addition to CSS mask, we can also use the CSS clip-path property to cut the corners. Each corner can be defined with three points.

The shape consists of two points at each end of the cut, and one between them to form the angle.

The other corners will have the same value with an offset of 100%. This gives us the final code with a total of 12 points — three per corner.

/* I will define T = [1-tan((angle-90)/2)]*size */ clip-path: polygon( /* Top-left corner */ 0 T, size size,0 T, /* OR 0 0 */ /* Top-right corner */ calc(100% - T) 0,calc(100% - size) size,100% T, /* OR 100% 0 */ /* Bottom-right corner*/ 100% calc(100% - T),calc(100% - size) calc(100% - size), calc(100% - T) 100%, /* OR 100% 100% */ /* Bottom-left corner */ T 100%, size calc(100% - size),0 calc(100% - T) /* OR 0 100% */ )

Notice the OR comments in that code. It defines the code we have to consider if we want to disable a particular corner. To cut a corner, we use three points. To uncut a corner, we use one point — which is nothing but the coordinate of that corner.

Border-only angled cut

Oof, we have reached the last and trickiest shape at last! This one can be achieved with either gradients or clip-path, but let’s go with the clip-path approach.

Things would get complex and verbose if we go with the gradient approach. Here’s a demo that illustrates that point:

CodePen Embed Fallback

There are nine gradients total, and I am still not done with the calculation. As you can tell, the thickness of the border is incorrect, plus the final result is unsatisfying due to the nature of gradients and their anti-aliasing issues. This approach might be a good exercise to push the limit of gradients, but I don’t recommend it in a production environment.

So, back to the clip-path method. We will still wind up with verbose code, but less of a big deal since the generator can do the job for us with a cleaner end result.

Here is an overview of the path. I am adding a small gap to better see the different points but we should have an overlap of points instead.

We have 13 outer points (the ones in black) and 13 inner points (the ones in blue).

The way we calculate the outer points is the same as how we did it for the regular angled cut. For the inner points, however, we need more math. Don’t worry, I’ll spare you some “boring” geometry explanation for this one. I know most of you don’t want it, but in case you need to dig into this, you can check the JavaScript file of the generator to find the code and the math I am using to generate the shape.

The 180deg special case

Before we end, there’s a special case for the angle cut I want to call out. It’s where we use an angle equal to 180deg. Here’s what that produces:

We have a straight line on the corner so we can optimize the clip-path code. For the full shape, we can use eight points (two points per corner) instead of 12. And for the border-only version, we can use 18 points (nine inner points and outer points) instead of 26. In other words, we can remove the middle point.

The border-only shape can also be made using gradients. But rather than using nine gradients like we did before, we can get away with only four linear gradients and a clean result.

CodePen Embed Fallback Conclusion

We just combined CSS masks with gradients to create some fancy shapes without resorting to hacks and a lot of code! We also experienced just how much it takes to strike the right balance of code to get the right results. We even learned a few tricks along the way, like changing values by one or even half a unit. CSS is super powerful!

But, as we discussed, the online generator I made is a great place to get the code you need rather than writing it out by hand. I mean, I went through all the work of figuring out how all of this works and I would likely still need to reference this very article to remember how it’s all put together. If you can memorize all of this, kudos! But it’s nice to have a generator to fall back on.

Tricks to Cut Corners Using CSS Mask and Clip-Path Properties originally published on CSS-Tricks. You should get the newsletter.

Write HTML, the HTML Way (Not the XHTML Way)

Css Tricks - Mon, 03/21/2022 - 10:08am

You may not use XHTML (anymore), but when you write HTML, you may be more influenced by XHTML than you think. You are very likely writing HTML, the XHTML way.

What is the XHTML way of writing HTML, and what is the HTML way of writing HTML? Let’s have a look.

HTML, XHTML, HTML

In the 1990s, there was HTML. In the 2000s, there was XHTML. Then, in the 2010s, we switched back to HTML. That’s the simple story.

You can tell by the rough dates of the specifications, too: HTML “1” 1992, HTML 2.0 1995, HTML 3.2 1997, HTML 4.01 1999; XHTML 1.0 2000, XHTML 1.1 2001; “HTML5” 2007.

XHTML became popular when everyone believed XML and XML derivatives were the future. “XML all the things.” For HTML, this had a profound effect: The effect that we learned to write it the XHTML way.

The XHTML way of writing HTML

The XHTML way is well-documented, because XHTML 1.0 describes in great detail in its section on “Differences with HTML 4”:

  • Documents must be well-formed.
  • Element and attribute names must be in lower case.
  • For non-empty elements, end tags are required.
  • Attribute values must always be quoted.
  • Attribute minimization is not supported.
  • Empty elements need to be closed.
  • White space handling in attribute values is done according to XML.
  • Script and style elements need CDATA sections.
  • SGML exclusions are not possible.
  • The elements with id and name attributes, like a, applet, form, frame, iframe, img, and map, should only use id.
  • Attributes with pre-defined value sets are case-sensitive.
  • Entity references as hex values must be in lowercase.

Does this look familiar? With the exception of marking CDATA content, as well as dealing with SGML exclusions, you probably follow all of these rules. All of them.

Although XHTML is dead, many of these rules have never been questioned again. Some have even been elevated to “best practices” for HTML.

That is the XHTML way of writing HTML, and its lasting impact on the field.

The HTML way of writing HTML

One way of walking us back is to negate the rules imposed by XHTML. Let’s actually do this (without the SGML part, because HTML isn’t based on SGML anymore):

  • Documents may not be well-formed.
  • Element and attribute names may not be in lower case.
  • For non-empty elements, end tags are not always required.
  • Attribute values may not always be quoted.
  • Attribute minimization is supported.
  • Empty elements don’t need to be closed.
  • White space handling in attribute values isn’t done according to XML.
  • Script and style elements don’t need CDATA sections.
  • The elements with id and name attributes may not only use id.
  • Attributes with pre-defined value sets are not case-sensitive.
  • Entity references as hex values may not only be in lowercase.

Let’s remove the esoteric things; the things that don’t seem relevant. This includes XML whitespace handling, CDATA sections, doubling of name attribute values, the case of pre-defined value sets, and hexadecimal entity references:

  • Documents may not be well-formed.
  • Element and attribute names may not be in lowercase.
  • For non-empty elements, end tags are not always required.
  • Attribute values may not always be quoted.
  • Attribute minimization is supported.
  • Empty elements don’t need to be closed.

Peeling away from these rules, this looks a lot less like we’re working with XML, and more like working with HTML. But we’re not done yet.

“Documents may not be well-formed” suggests that it was fine if HTML code was invalid. It was fine for XHTML to point to wellformedness because of XML’s strict error handling. But while HTML documents work even when they contain severe syntax and wellformedness issues, it’s neither useful for the professional — nor our field — to use and abuse this resilience. (I’ve argued this case before in my article, “In Critical Defense of Frontend Development.”)

The HTML way would therefore not suggest “documents may not be well-formed.” It would also be clear that not only end, but also start tags aren’t always required. Rephrasing and reordering, this is the essence:

  • Start and end tags are not always required.
  • Empty elements don’t need to be closed.
  • Element and attribute names may be lower or upper case.
  • Attribute values may not always be quoted.
  • Attribute minimization is supported.
Examples

How does this look like in practice? For start and end tags, be aware that many tags are optional. A paragraph and a list, for example, are written like this in XHTML:

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p> <ul> <li>Praesent augue nisl</li> <li>Lobortis nec bibendum ut</li> <li>Dictum ac quam</li> </ul>

In HTML, however, you can write them using only this code (which is valid):

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. <ul> <li>Praesent augue nisl <li>Lobortis nec bibendum ut <li>Dictum ac quam </ul>

Developers also learned to write void elements, like so:

<br />

This is something XHTML brought to HTML, but as the slash has no effect on void elements, you only need this:

<br>

In HTML, you can also just write everything in all caps:

<A HREF="https://css-tricks.com/">CSS-Tricks</A>

It looks like you’re yelling and you may not like it, but it’s okay to write it like this.

When you want to condense that link, HTML offers you the option to leave out certain quotes:

<A HREF=https://css-tricks.com/>CSS-Tricks</A>

As a rule of thumb, when the attribute value doesn’t contain a space or an equal sign, it’s usually fine to drop the quotes.

Finally, HTML–HTML — not XHTML–HTML — also allows to minimize attributes. That is, instead of marking an input element as required and read-only, like this:

<input type="text" required="required" readonly="readonly">

You can minimize the attributes:

<input type="text" required readonly>

If you’re not only taking advantage of the fact that the quotes aren’t needed, but that text is the default for the type attribute here (there are more such unneeded attribute–value combinations), you get an example that shows HTML in all its minimal beauty:

<input required readonly> Write HTML, the HTML way

The above isn’t a representation of where HTML was in the 90s. HTML, back then, was loaded with <table> elements for layout, packed with presentational code, largely invalid (as it’s still today), with wildly varying user agent support. Yet it’s the essence of what we would have wanted to keep if XML and XHTML hadn’t come around.

If you’re open to a suggestion of what a more comprehensive, contemporary way of writing HTML could look like, I have one. (HTML is my main focus area, so I’m augmenting this by links to some of my articles.)

  1. Respect syntax and semantics.
  2. Use the options HTML gives you, as long as you do so consistently.
    • Remember that element and attribute names may be lowercase or uppercase.
  3. Keep use of HTML to the absolute minimum
    • Remember that presentational and behavioral markup is to be handled by CSS and JavaScript instead.
    • Remember that start and end tags are not always required.
    • Remember that empty elements don’t need to be closed.
    • Remember that some attributes have defaults that allow these attribute–value pairs to be omitted.
    • Remember that attribute values may not always be quoted.
    • Remember that attribute minimization is supported.

It’s not a coincidence that this resembles the three ground rules for HTML, that it works with the premise of a smaller payload also leading to faster sites, and that this follows the school of minimal web development. None of this is new — our field could merely decide to rediscover it. Tooling is available, too: html-minifier is probably the most established and able to handle all HTML optimizations.

You’ve learned HTML the XHTML way. HTML isn’t XHTML. Rediscover HTML, and help shape a new, modern way of writing HTML — which acknowledges, but isn’t necessarily based on XML.

Write HTML, the HTML Way (Not the XHTML Way) originally published on CSS-Tricks. You should get the newsletter.

Font Fashion Week

Typography - Thu, 03/17/2022 - 2:30am

Read the book, Typographic Firsts

Font Fashion Week is just around the corner! It’s a brand new series of free online events organized by I Love Typography to celebrate the latest trends in type design.

The post Font Fashion Week appeared first on I Love Typography.

CSS-Tricks is joining DigitalOcean!

Css Tricks - Tue, 03/15/2022 - 2:18am

Hey hey!

I’ve got a big announcement to make here. (Where’s my gong? I feel like this really needs a good gong hit.)

CSS-Tricks, this very website you’re looking at, has been acquired by DigitalOcean!

You can hear from them directly on the DigitalOcean blog as well.

This will be the most fun if we have a conversation about it, so allow me to kick it off. I’ll pretend to be you at first and then you can be you in the comments.

Hey, congrats!

Thanks! 

DigitalOcean? Aren’t they like a… web host?

They are! A very good one. You can build anything on DigitalOcean infrastructure (probably best to think of them as a cloud computing platform that has tools ranging from servers to managed Kubernetes). One thing I think is particularly cool is their new App Platform which to me feels extra aligned with front-end developers like me. We’ve covered that before. Also, their whole concept of Droplets (super simple servers that are quick to spin up) has been transformative in the industry.  But more importantly about this acquisition… have you seen their DigitalOcean Community site? It’s loaded with top-notch developer education. DigitalOcean has been super committed to that for a long time, and to me makes this a very natural and well-suited move.

What happens to CSS-Tricks?

The site and content is staying right here. DigitalOcean is committed to continuing to produce high-quality content on front-end development and tending to the trove of content that exists here already. 

Will you still be running CSS-Tricks?

I will be working with the DigitalOcean team as an advisor as we transition CSS-Tricks to DigitalOcean’s management, and will then step back to focus on my other projects. 

Why now?

When I started CSS-Tricks in 2007, I couldn’t have imagined how much it would grow. I wanted it to grow, that was the plan, but now it’s a far bigger job than any one person can do. That, I was never ready for. 

Let me take a quick moment to give some thanks here. I had the incredible help of Geoff as lead editor, sponsor wrangler, and site manager. Robin turned the newsletter into the must-read industry rag it is now. It’s a family business as well! My wife Miranda helped with the books, working with authors, and her guidance on running the site as a proper publication has led the site where it is. I literally couldn’t have done it without any one of them. And of course, the incredible group of authors, with a special shout out to Sarah, a long-time staff writer and friend.

A small but mighty team, indeed. And that’s the thing. CSS-Tricks deserves more human muscle behind it than I’ve been able to provide for it. That’s where DigitalOcean comes in. That’s the “why now.” They have the resources to put behind CSS-Tricks, and the motivation to do so. I fully trust them to do it, as they’ve been successfully doing it themselves for a long time.

OK! Your turn! If you have any thoughts or questions, feel free to comment below. We’ll read them all and publish anything useful and constructive.

CSS-Tricks is joining DigitalOcean! originally published on CSS-Tricks. You should get the newsletter.

Featured Fonts: March 2022

Typography - Wed, 03/09/2022 - 2:30am

Read the book, Typographic Firsts

Welcome to our March edition of Featured Fonts. Before we get to our three picks, we’d love to tell you that the schedule for Font Fashion Week is up. FFW is a series of free online events organized by I Love Typography to celebrate the latest trends in international type design. Tickets (free tickets!) will […]

The post Featured Fonts: March 2022 appeared first on I Love Typography.

Celebrating women-led foundries

Typography - Tue, 03/08/2022 - 3:00am

Read the book, Typographic Firsts

I Love Typography launches a mentorship program for women-led (or co-led) foundries. Today, as we celebrate the first International Women’s Day since launching our store, we are thrilled to announce that we are starting a mentorship program for women-led or co-led foundries which will focus on providing regular advice on business development and marketing strategy.

The post Celebrating women-led foundries appeared first on I Love Typography.

Typefaces for Human-centered Branding

Typography - Mon, 03/07/2022 - 2:30am

Read the book, Typographic Firsts

If typography is the voice of a brand, what sort of typeface would fit a human-centered one? Award-winning type designer, educator, and typographic branding expert, Dr. Nadine Chahine, recommends typefaces ideally suited to human-centered branding design — typefaces able to project modernity while remaining anchored in humanity.

The post Typefaces for Human-centered Branding appeared first on I Love Typography.

Say Hello to selectmenu, a Fully Style-able select Element

Css Tricks - Thu, 03/03/2022 - 5:35am

I want to introduce you to a new, experimental form control called <selectmenu>. We’ll get deep into it, including how much easier it is to style than a traditional <select> element. But first, let’s fill in some context about why something like <selectmenu> is needed in the first place, as it’s still evolving and in development.

Ask any web developer what they think is missing from the web platform today, chances are the ability to style form controls will be on their list. In fact, form styling was voted as one of the top-10 missing things in the State of CSS Survey in 2020. It was then further surveyed by Greg Whitworth who showed that <select> was the control web developers were having the most problems styling with CSS.

While it’s relatively easy to style the appearance of the button part of a <select> (the thing you see in the page when the popup is closed), it’s almost impossible to style the options (the thing you see when the popup is open), let alone add more content within the popup.

The default UI for a <select> element in Safari

As a result, design systems and component libraries have been rolling out their own selects, made from scratch using custom HTML markup, CSS, and often a lot of JavaScript, in order to have something that integrates nicely with the other components.

Unfortunately, doing so correctly with the right accessibility semantics, keyboard support, and popup positioning is not easy. Web developers have poured hours and hours over the years, trying to solve the same problems over and over, and there are many inaccessible selects out there.

It’s about time we got a properly style-able built-in <select> so we don’t have to write this code ever again!

The Open UI initiative

Open UI is a group of developers, designers, and browser implementers who set out to solve this exact problem, and while they’re at it, tackle other missing controls too.

The purpose of Open UI is to eventually make it possible for web developers to style and extend built-in UI controls (this includes <select>, but dropdowns, checkboxes, radio buttons, and others too). To achieve this, they produce specifications for how these controls should be implemented in the web platform as well as the accessibility requirements they should address.

The project is still in its infancy, but things are moving fast and, as we’ll see below, exciting things are already happening.

You can join the group and participate in the meetings, research, and specification efforts.

The <selectmenu> control

Based on the Open UI’s <select> proposal, the implementation of a new <selectmenu> control has started in Chromium! The work is done by the Microsoft Edge team, in collaboration with the Google Chrome team. It’s even already available in Chromium-based browsers by enabling the “Experimental Web Platform features” flag in the about:flags page.

<selectmenu> is a new built-in control that provides an option selection user experience, just like <select>, with a button showing the selected value label, a popup that appears when that button is clicked, and a list of options that get displayed.

Why a new name?

Why not just replace the existing <select> control? The name “selectmenu” started as a working name, but it seems to have stuck so far, and no one has come up with anything better yet.

More importantly, the existing <select> control has been used on the web for a very long time. As such, it can probably never be changed in any significant way without causing major compatibility issues.

So, the plan (and remember this is all still very experimental) is for <selectmenu> to be a new control, independent from <select>.

Try it out today

This isn’t ready for production use yet, but if you’re as excited as I am about using it, here’s how:

  1. Open a Canary version of a Chromium-based browser (Chrome, Edge).
  2. Switch the “Experimental Web Platform features” flag in the about:flags page and restart.
  3. Replace any <select> by <selectmenu> in a web page!

That’s it! It won’t do much by default, but as we’ll see later, you’ll be able to style and extend the control quite extensively with this one tag name change.

We love feedback!

Before we go into how to use the control, if you do use it, the Open UI group and people working on the implementation in Chromium would love to hear your feedback if you have any.

By being an early tester, you can actively help them make the control better for everyone. So, if you encounter bugs or limitations with the design of the control, please send your feedback by creating an issue on the Open UI GitHub repository!

And now, let’s talk about how the control works.

The anatomy of a <selectmenu> control

Because the various parts of the selectmenu can be styled, it’s important to first understand its internal anatomy.

  • <selectmenu> is the root element that contains the button and listbox.
  • <button> is the element that triggers the visibility of the listbox.
  • <selected-value> is the element that displays the value of the currently selection option (optional). Note that this part does not necessarily have to be placed inside the <button> part.
  • <listbox> is the wrapper that contains the <option>s and <optgroup>s.
  • <optgroup> groups s together with an optional label.
  • <option> represents the potential value that can be chosen by the user. There can be one or more.
Default behavior

The default behavior of the <selectmenu> control mimics the behavior of the <select> control. You can use it just like a native <select>, with the following minimal markup.

<selectmenu> <option>Option 1</option> <option>Option 2</option> <option>Option 3</option> </selectmenu>

When doing so, the default <button>, <selected-value>, and <listbox >are created for you.

Styling parts of the control

This is where things become interesting! One way to style the control to match your requirements is to use the CSS ::part() pseudo-element to select the different parts within the control’s anatomy that you wish to style.

Consider the following example where ::part() is used to style the button and the listbox parts:

<style> .my-select-menu::part(button) { color: white; background-color: #f00; padding: 5px; border-radius: 5px; } .my-select-menu::part(listbox) { padding: 10px; margin-top: 5px; border: 1px solid red; border-radius: 5px; } </style> <selectmenu class="my-select-menu"> <option>Option 1</option> <option>Option 2</option> <option>Option 3</option> </selectmenu>

The above example results in the following style:

::part() can be used to style the <button>, <selected-value>, and <listbox> parts of the control.

Use your own markup

If the above isn’t enough for your needs, you can customize the control much more by providing your own markup to replace the default one, and extend or re-order the parts.

A <selectmenu> has named slots that can be referenced to replace the default parts. For example, to replace the default button with your own, you can do the following:

<style> .my-custom-select [slot='button'] { display: flex; align-content: center; } .my-custom-select button { padding: 5px; border: none; background: #f06; border-radius: 5px 0 0 5px; color: white; font-weight: bold; } .my-custom-select .label { padding: 5px; border: 1px solid #f06; border-radius: 0 5px 5px 0; } </style> <selectmenu class="my-custom-select"> <div slot="button"> <button behavior="button">Open</button> <span class="label">Choose an option</span> </div> <option>Option 1</option> <option>Option 2</option> <option>Option 3</option> </selectmenu>

The slot="button" attribute on the outer <div> tells the <selectmenu> to replace its default button with the contents of the <div>.

The behavior="button" attribute on the inner <button> tells the browser that this element is what we want to use as the new button. The browser will automatically apply all the click and keyboard handling behavior to this element as well as the appropriate accessibility semantics.

The above code snippet results in the following style:

Note that the slot and behavior attributes can also be used on the same element.

You can replace the default listbox part in a similar fashion:

<style> .my-custom-select [popup] { width: 300px; display: grid; grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); gap: 10px; padding: 10px; box-shadow: none; margin: 10px 0; border: 1px solid; background: #f7f7f7; } </style> <selectmenu class="my-custom-select"> <div slot="listbox"> <div popup="popup" behavior="listbox"> <option>Option 1</option> <option>Option 2</option> <option>Option 3</option> <option>Option 4</option> <option>Option 5</option> </div> </div> </selectmenu>

Interestingly, the <div popup> used here is also being proposed by Open UI and implemented in Chromium at the moment.

The element with behavior="listbox" is required to be a <div popup>. Applying behavior="listbox" tells the browser to open this element when the <selectmenu> button is clicked, and the user can select <option>s inside it with mouse, arrow keys, and touch.

The above code snippet results in the following style:

Extending the markup

Not only can you replace the default parts with your own, as seen above, you can also extend the control’s markup by adding new elements. This can be useful to augment the listbox or button with extra information, or to add new functionality.

Consider the following example:

<style> .my-custom-select [slot='button'] { display: flex; align-items: center; gap: 1rem; } .my-custom-select button { border: none; margin: 0; padding: 0; width: 2rem; height: 2rem; border-radius: 50%; display: grid; place-content: center; } .my-custom-select button::before { content: '\25BC'; } .my-custom-select [popup] { padding: 0; } .my-custom-select .section { padding: 1rem 0 0; background: radial-gradient(ellipse 60% 50px at center top, #000a 0%, transparent 130%); } .my-custom-select h3 { margin: 0 0 1rem 0; text-align: center; color: white; } .my-custom-select option { text-align: center; padding: 0.5rem; } </style> <selectmenu class="my-custom-select"> <div slot="button"> <span class="label">Choose a plant</span> <span behavior="selected-value" slot="selected-value"></span> <button behavior="button"></button> </div> <div slot="listbox"> <div popup="popup" behavior="listbox"> <div class="section"> <h3>Flowers</h3> <option>Rose</option> <option>Lily</option> <option>Orchid</option> <option>Tulip</option> </div> <div class="section"> <h3>Trees</h3> <option>Weeping willow</option> <option>Dragon tree</option> <option>Giant sequoia</option> </div> </div> </div> </selectmenu>

Here we’re using custom markup to wrap the list of options and create our own content as seen below:

Replacing the entire shadow DOM

Finally, and if the above wasn’t enough, you can also extend the control’s markup by replacing its default shadow DOM altogether by calling attachShadow(). For example, the demo in the previous section could be modified as follows:

<selectmenu id="my-custom-select"></selectmenu> <script> const myCustomSelect = document.querySelector('#my-custom-select') const shadow = myCustomSelect.attachShadow({ mode: 'closed' }) shadow.innerHTML = ` <style> .button-container { display: flex; align-items: center; gap: 1rem; } button { border: none; margin: 0; padding: 0; width: 2rem; height: 2rem; border-radius: 50%; display: grid; place-content: center; } button::before { content: '\\0025BC'; } [popup] { padding: 0; } .section { padding: 1rem 0 0; background: radial-gradient(ellipse 60% 50px at center top, #000a 0%, transparent 130%); } h3 { margin: 0 0 1rem 0; text-align: center; color: white; } option { text-align: center; padding: 0.5rem; } option:hover { background-color: lightgrey; } </style> <div class="button-container"> <span class="label">Choose a plant</span> <span behavior="selected-value" slot="selected-value"></span> <button behavior="button"></button> </div> <div popup="popup" behavior="listbox"> <div class="section"> <h3>Flowers</h3> <option>Rose</option> <option>Lily</option> <option>Orchid</option> <option>Tulip</option> </div> <div class="section"> <h3>Trees</h3> <option>Weeping willow</option> <option>Dragon tree</option> <option>Giant sequoia</option> </div> </div> ` </script>

Written this way, the <selectmenu>‘s custom markup is fully encapsulated in its shadow DOM. The <selectmenu> can therefore be dropped into any page without risk of interference from the surrounding content’s styles.

Closing remarks

As we’ve seen, the new experimental <selectmenu> control offers a lot of flexibility when it comes to styling and even extending a traditional <select>. And it does this in all the right ways, because it’s built into the browser where accessibility and viewport-aware positioning are handled for you.

Open UI has more documentation about <selectmenu>, and if you want to see more code showing how to use the <selectmenu>, here are a few demos as well.

Again, this is work in progress and will most certainly change as a result of feedback received by the Open UI group.

I can’t wait to see specifications start to appear in HTML and CSS standard bodies, and for the implementation to become more stable, as well as see other browser engines getting interested in this. You can help make this happen! Testing the control, reporting issues, or getting involved are all great ways to help push this effort forward.

Say Hello to selectmenu, a Fully Style-able select Element originally published on CSS-Tricks. You should get the newsletter.

Build Membership Businesses with Memberful

Css Tricks - Thu, 03/03/2022 - 5:33am

(This is a sponsored post.)

What would your business be like if you sold memberships? It might be more than fun to think about, in fact, it might just be transformative. With membership, would you include little add-ons or perks for your biggest fans? Or could it become the entire core of what you do? Likewise, what might you help your clients build?

Whatever you decide to do (or perhaps what a client has hired you to do), you can get it done with Memberful. It’s the best software for building membership businesses, used by the biggest creators on the web.

Memberful is for developers.

You have a goal in mind: to build a great member-powered web experience. But you’re a developer and want to build how you want to build. Good. Memberful is here to support that.

Memberful maintains a full-featured GraphQL API (complete with GraphiQL explorer), webhooks, and OAth Single Sign-on to make it easy to integrate seamlessly with any stack.

Your main site in Rails? No problem. You wanna do a Jamstack thing? Perfect. Do you have a React-powered app through and through? That’ll work.

You don’t have to build entirely from scratch.

For example, Memberful maintains a best-in-class WordPress plugin that easily gates content and adds membership to your website. So if you happen to use WordPress as your CMS, or are thinking of using it to build your website, you’ve got a first-class integration to work with.

If you’re looking to add membership to your existing business, you’ll want a solution that works with your existing technology, so you can launch a new revenue stream without rebuilding your entire tech stack.

You don’t even need to build a website to use Memberful.

If you’re not looking to gate access to content on a custom website, you won’t need a website at all to use Memberful. You can use Memberful’s hosted landing page feature to sell your memberships, and then deliver your member benefits like a private podcast, protected downloads, and newsletters right through the platform — no website required.

Say you already use other tools for your business. Maybe you do all your emailing with MailChimp. Great! Memberful fully integrates with MailChimp. Is Discord your community hub? No problem, Memberful seamlessly integrates with Discord, meaning you can offer paid subscribers perks that are unique to Discord, things like special channels or access roles.

What are some common use cases for Memberful?
  • Private Podcasts
  • Subscription Newsletters
  • Selling digital goods (or physical!)
  • Building communities
  • Membership-driven educational courses

Memberful handles the hard stuff so you can focus on what you do best, while earning revenue quickly. Even advanced features like gift subscriptions, coupons, referrals, free and paid trials and more, are right there for you to take advantage of.

Who handles all the emails?

Memberful does, and you get 100% control of the brand. Yet another thing you won’t need to worry about, which can otherwise be an awful lot of work and technical debt. I’m talking transactional emails here, like signup confirmation emails, welcome emails, forgot password emails, etc.

How does the money work?

Memberful has a free plan to get your feet wet. You can build 2 subscription plans and do website integrations. The PRO plan starts at $25/month and lowers transaction fees to 4.9% down from 10% on the free plan.

Where do those subscription payments go? You connect your Stripe account, so that money goes there, which is the best-in-business payment provider. That means you can offer additional features like Apple Pay and Google Pay which are great for lowering checkout friction for potential customers.

Have questions? Memberful has always-real-human based support at all times to help you.

Build Membership Businesses with Memberful originally published on CSS-Tricks. You should get the newsletter.

7 Fresh Links on Performance For March 2022

Css Tricks - Wed, 03/02/2022 - 11:26am

I have a handful of good links to articles about performance that are burning a hole in my bookmarks folder, and wanna drop them here to share.

The new WebPageTest website design

7 Fresh Links on Performance For March 2022 originally published on CSS-Tricks. You should get the newsletter.

Steven Heller’s Font of the Month: Nicholas

Typography - Wed, 03/02/2022 - 2:45am

Read the book, Typographic Firsts

In this seventh episode of Font of the Month, Steven Heller goes back to the future with Nick Shinn’s magnificent Nicholas typeface family. Reminiscing about the great Herb Lubalin’s extra tight type settings in Avant Garde and Fact magazines of the 1960s, and then back to the present day and a typeface inspired by that era and those legends.

The post Steven Heller’s Font of the Month: Nicholas appeared first on I Love Typography.

Ahmad Shadeed: Use Cases For CSS fit-content

Css Tricks - Tue, 03/01/2022 - 5:41am

Ahmad Shadeed covers the CSS fit-content sizing keyword. It’s useful! It just doesn’t come up super often. I find myself using min-content a lot more, like when setting up the height of a grid-template-row.

The fit-content keyword is actually closely related to min-content and max-content — it just has a little heuristic it follows that Ahmad nicely illustrates as a flow chart.

“Use Cases For CSS fit-content” by Ahmad Shadeed

My favorite use case is covered here: sizing a <figure> with fit-content, so that it neatly wraps around the <img>. That way, even if the image doesn’t fill the parent space, and it can remain block-level.

We also covered PPK’s deep dive on fit-content last year. One of the key takeaways for understanding it is knowing that is it essentially a shorthand way of writing:

.box { width: fit-content; /* ... is the same as ... */ width: auto; min-width: min-content; max-width: max-content; }

To Shared LinkPermalink on CSS-Tricks

Ahmad Shadeed: Use Cases For CSS fit-content originally published on CSS-Tricks. You should get the newsletter.

Ahmad Shadeed: Use Cases For CSS fit-content

Css Tricks - Tue, 03/01/2022 - 5:41am

Ahmad Shadeed covers the CSS fit-content sizing keyword. It’s useful! It just doesn’t come up super often. I find myself using min-content a lot more, like when setting up the height of a grid-template-row.

The fit-content keyword is actually closely related to min-content and max-content — it just has a little heuristic it follows that Ahmad nicely illustrates as a flow chart.

“Use Cases For CSS fit-content” by Ahmad Shadeed

My favorite use case is covered here: sizing a <figure> with fit-content, so that it neatly wraps around the <img>. That way, even if the image doesn’t fill the parent space, and it can remain block-level.

We also covered PPK’s deep dive on fit-content last year. One of the key takeaways for understanding it is knowing that is it essentially a shorthand way of writing:

.box { width: fit-content; /* ... is the same as ... */ width: auto; min-width: min-content; max-width: max-content; }

To Shared LinkPermalink on CSS-Tricks

Ahmad Shadeed: Use Cases For CSS fit-content originally published on CSS-Tricks. You should get the newsletter.

IE Down, Edge Up… Global Browser Usage Stats Are for Cocktail Parties and Conference Slides

Css Tricks - Mon, 02/28/2022 - 1:14pm

I enjoy articles like Hartley Charlton’s “Microsoft Edge Looks Set to Overtake Safari as World’s Second Most Popular Desktop Browser.” It’s juicy! We know these massive players in the browser market care very much about their market share, so when one passes another it’s news. Like an Olympic speed skater favored for the gold getting a bronze instead, or the like.

Microsoft Edge is now used on 9.54 percent of desktops worldwide, a mere 0.3 percent behind Apple’s Safari, which stands at 9.84 percent. Google Chrome continues to hold first place with an overwhelming 65.38 percent of the market. Mozilla Firefox takes fourth place with 9.18 percent.

In January 2021, Safari held a 10.38 percent market share and appears to be gradually losing users to rival browsers over time. If the trend continues, Apple is likely to slip to third or fourth place in the near future.

Scoping the data down even by continent is entirely different. Like in Europe, Edge has already passed Safari, but in North America, the gap is still 5%.

Source: MacRumors.com

What does it matter to you or me? Nothing, I hope. These global stats should mean very little to us, outside a little casual nerdy cocktail party chatter. Please don’t make decisions about what to support and not support based on global statistics. Put some kind of basic analytics in place on your site, get data from actual visits, and make choices on that data. That’s the only data that matters.

Alan Dávalos’ “The baseline for web development in 2022” paints a picture of what we should be supporting based again on global browser usage statistics.

Globally, IE’s current market share is under 0.5%. And even in Japan, which has a higher market share of IE compared to other countries, IE’s market share is close to 2% and has a downward tendency.

Until now we kept supporting IE due to its market share. But now, there are basically no good reasons to keep supporting IE.

Again it seems so bizarre to me that any of us would make a choice on what to support based on a global usage statistic. Even when huge players make choices, they do it based on their own data. When Google “dropped” IE 11 (they still serve a perfectly fine baseline experience), they “did the math.” WordPress, famously powering somewhere in the “a third of the whole internet” range, factored in usage of their own product.

Even if you’re building a brand new product and trying to make these choices, you’ll have analytic data soon enough, and can make future-facing support choices based on that as it rolls in.

IE Down, Edge Up… Global Browser Usage Stats Are for Cocktail Parties and Conference Slides originally published on CSS-Tricks. You should get the newsletter.

Syndicate content
©2003 - Present Akamai Design & Development.