Web Standards

`lh` and `rlh` units

Css Tricks - Tue, 05/05/2020 - 8:22am

There’s some new units I was totally unaware of from the Level 4 spec for CSS values! The lh unit is “equal to the computed value of line-height” and rlh is the same only of the root element (probably the <html> element) rather than the current element.

Why would that be useful? Šime Vidas’ has a strong point:

“Vertical Inline Centering” of an icon .inline-icon { display: inline-block; width: 1lh; height: 1lh; }

The post `lh` and `rlh` units appeared first on CSS-Tricks.

List Style Recipes

Css Tricks - Tue, 05/05/2020 - 4:10am

Lists are a fundamental part of HTML! They are useful in things like blog posts for listing out steps, recipes for listing ingredients, or items in a navigation menu. Not only are they an opportunity for styling, but they have accessibility implications. For example, the number of items in a list is announced in a screen reader to give some context to the list.

Let’s focus on styling lists here, mostly just ordered and unordered lists (with apologies for snubbing our friend the definition list), and somewhat unusual styling situations.

The Basics

Before you do anything too fancy, know that there is quite few settings for list-style-type that might cover your needs out of the gate.

CodePen Embed Fallback The Break in the Middle

Ordered lists can start at any number you want them to.

CodePen Embed Fallback The Nested Decimals CodePen Embed Fallback The Reversed Top 10 List

A single reversed attribute will do the trick.

CodePen Embed Fallback Image Bullets

The best bet is using a background-image on a pseudo-element. You’d think list-style-image would be the way to go, but it’s extremely limited. For example, you can’t position it or even resize it.

CodePen Embed Fallback Emoji Bullets CodePen Embed Fallback Hand-Picked “Random” Order

The value attribute will set a list item to use the marker relevant for that position.

CodePen Embed Fallback Custom Text Counters

Can be done with pseudo-elements for the most control, but there is also list-style-type: '-';

CodePen Embed Fallback Inside vs. Outside

Things line up nicer with list-style-position: outside; (the default value), but the list markers render outside the box, so you have to be careful not to cut them off. They could hang off the edge of the browser window, or overflow: hidden; will hide them completely. The last two examples here have a trick to mimic the nicer alignment while rendering inside the element.

CodePen Embed Fallback Colored Bullets

Three ways here:

  1. ::marker (newest and easiest)
  2. Classic pseudo-element style
  3. background-image (this one is an SVG Data URL so you can manipulate the color from the CSS)
CodePen Embed Fallback Columized List

The number of columns can be automatic.

CodePen Embed Fallback Colored Circle Numbers CodePen Embed Fallback Custom Cycling List Symbols

One-offs can be done with list-style: symbols() and reusable sets can be made with @counter-style then used. Note this is only supported in Firefox at the time of writing.

CodePen Embed Fallback

The post List Style Recipes appeared first on CSS-Tricks.

Angular + Jamstack! (Free Webinar)

Css Tricks - Tue, 05/05/2020 - 4:00am

(This is a sponsored post.)

It’s easy to think that working with Jamstack means working with some specific set of technologies. That’s how it’s traditionally been packaged for us. Think LAMP stack, where Linux, Apache, MySQL and PHP are explicit tools and languages. or MEAN or MERN or whatever. With Jamstack, the original JAM meant JavaScript, APIs, and Markup. That’s not specific technologies so much as a loose philosophy.

That’s cool, because it means we can bring our own set of favorite technologies, and then figure out how to use that philosophy for the most benefit. That can mean bringing our favorite CMS, favorite build tools, and even favorite front-end frameworks.

That’s the crux of Netlify’s upcoming webinar on using Angular in the Jamstack. They’ll walk through where Angular fits into the Jamstack architecture, how to develop with Angular in the stack, and the benefits of working this way. Plus you get to hang with Tara Z. Manicsic, which is worth it right there.

The webinar is free and scheduled for May 13 at 9:00am Pacific Time.

Direct Link to ArticlePermalink

The post Angular + Jamstack! (Free Webinar) appeared first on CSS-Tricks.

Playing With (Fake) Container Queries With watched-box & resizeasaurus

Css Tricks - Mon, 05/04/2020 - 2:40pm

Heydon’s <watched-box> is a damn fantastic tool. It’s a custom element that essentially does container queries by way of class names that get added to the box based on size breakpoints that are calculated with ResizeObserver. It’s like a cleaner version of what Philip was talking about a few years ago.

I’m sure I’d be happy using <watched-box> on production, as it’s lightweight, has no dependencies, and has a straightforward approach.

For development, I had the idea of using Zach’s interesting little <resize-asaurus> web component. It wraps elements in another box that is resizeable via CSS and labels it with the current width. That way you don’t have to fiddle with the entire browser window to resize things — any given element becomes resizable. Again, just for development and testing reasons.

You’d wrap them together like…

<resize-asaurus> <watched-box widthBreaks="320px, 600px"> <div class="card"> ... </div> </watched-box> </resize-asaurus>

Which allows you to write CSS at breakpoints like…

.card { .w-gt-320px & { } .w-gt-600px & { } }

That’s surely not what the CSS syntax for container queries syntax will end up being, but it accomplishes the same thing with clear and understandable generated class names.

Example!

Live demo!

CodePen Embed Fallback

The post Playing With (Fake) Container Queries With watched-box & resizeasaurus appeared first on CSS-Tricks.

A Complete Guide to CSS Functions

Css Tricks - Mon, 05/04/2020 - 5:14am
Introduction

In programming, functions are a named portion of code that performs a specific task. An example of this could be a function written in JavaScript called sayWoof():

function sayWoof() {   console.log("Woof!"); }

We can use this function later in our code, after we have defined our desired behavior. For this example, any time you type sayWoof() in your website or web app’s JavaScript it will print “Woof!” into the browser’s console.

Functions can also use arguments, which are slots for things like numbers or bits of text that you can feed into the function’s logic to have it modify them. It works like this in JavaScript:

function countDogs(amount) {   console.log("There are " + amount + " dogs!"); }

Here, we have a function called countDogs() that has an argument called amount. When a number is provided for amount, it will take that number and add it to a pre-specified sentence. This lets us create sentences that tell us how many dogs we’ve counted.

countDogs(3); // There are 3 dogs! countDogs(276); // There are 276 dogs! countDogs("many"); // There are many dogs!

Some programming languages come with baked-in functions to help prevent you from having to reinvent the wheel for every new project. Typically, these functions are built to help make working with the main strengths and features of the language easier. 

Take libraries, for example. Libraries are collections of opinionated code made to help make development faster and easier, effectively just curated function collections — think FitVids.js for creating flexible video elements.

Like any other programming language, CSS has functions. They can be inserted where you’d place a value, or in some cases, accompanying another value declaration. Some CSS functions even let you nest other functions within them!

Basics of CSS Functions

Unlike other programming languages, we cannot create our own functions in CSS, per se. That kind of logic is reserved for CSS selectors, which allow you to create powerful conditional styling rules

As opposed to other programming languages — where the output of a function typically invisibly affects other logic down the line — the output of CSS functions are visual in nature. This output is used to control both layout and presentation of content. For example: 

.has-orange-glow { filter: drop-shadow(0.25rem 0 0.75rem #ef9035); }

The CSS filter function drop-shadow() uses the arguments we provide it to create an orange outer glow effect on whatever it is applied to.

In the following demo, I have a JavaScript function named toggleOrangeGlow that toggles the application of the class .has-orange-glow on the CSS-Tricks logo. Combining this with a CSS transition, we’re able to create a cool glowing effect:

CodePen Embed Fallback

You may be familiar with some CSS functions, but the language has a surprisingly expansive list! 

Much like any other technology on the web, different CSS functions have different levels of browser support. Make sure you research and test to ensure your experience works for everyone, and use things like @supports to provide quality alternate experiences.

Common CSS Functions url()

url() allows you to link to other resources to load them. This can include images, fonts, and even other stylesheets. For performance reasons, it’s good practice to limit the things you load via url(), as each declaration is an additional HTTP request.

CodePen Embed Fallback attr()

This function allows us to reach into HTML, snag an attribute’s content, and feed it to the CSS content property. You’ll commonly see attr() used in print stylesheets, where it is used to show the URL of a link after its text. Another great application of this function is using it to show the alt description of an image if it fails to load.

CodePen Embed Fallback calc()

If there’s one function you should spend some time experimenting with, it’s calc(). This function takes two arguments and calculates a result from the operator (+, -, *, /) you supply it, provided those arguments are numbers with or without an accompanying unit.

CodePen Embed Fallback

Unlike CSS preprocessors such as Sass, calc() can mix units, meaning you can do things like subtract 6rem from 100%. calc() is also updated on the fly, so if that 100% represents a width, it’ll still work if that width changes. calc() can also accept CSS Custom Properties as arguments, allowing you an incredible degree of flexibility

lang()

Including a lang attribute in your HTML is a really important thing to do. When present in your HTML, you’re able to use the lang() function to target the presence of the attribute’s value and conditionally apply styling based on it. 

One common use for this selector is to set language-specific quotes, which is great for things like internationalization. 

CodePen Embed Fallback

Clever designers and developers might also use it as a hook for styling translated versions of their sites, where cultural and/or language considerations mean there’s different perceptions about things like negative space.

:not()

This pseudo class selector will select anything that isn’t what you specify. For example, you could target anything that isn’t an image with body:not(img). While this example is dangerously powerful, scoping :not() to more focused selectors such as BEM’s block class can give you a great deal of versatility. 

CodePen Embed Fallback

Currently, :not() supports only one selector for its argument, but support for multiple comma-separated arguments (e.g. div:not(.this, .that)) is being worked on!

CSS Custom Properties

var() is used to reference a custom property declared earlier in the document. It is incredibly powerful when combined with calc().

An example of this is declaring a custom property called --ratio: 1.618; in the root of the document, then invoking it later in our CSS to control line height: line-height: var(--ratio);.

Here, var() is a set of instructions that tells the browser, “Go find the argument called --ratio declared earlier in the document, take its value, and apply it here.” 

Remember! calc() lets us dynamically adjust things on the fly, including the argument you supply via var().

This allows us to create things like modular scale systems directly in CSS with just a few lines of code. If you change the value of --ratio, the whole modular scale system will update to match.

In the following CodePen demo, I’ve done exactly just that. Change the value of --scale in the Pen’s CSS to a different number to see what I mean:

CodePen Embed Fallback

It’s also worth mentioning that JavaScript’s setProperty method can update custom properties in real time. This allows us to quickly and efficiently make dynamic changes to things that previously might have required a lot of complicated code to achieve. 

Color Functions

Another common place you see CSS functions is when working with color.

rgb() and rgba()

These functions allow you to use numbers to describe the red (r), green (g), blue (b), and alpha (a) levels of a color. For example, a red color with a hex value of #fb1010 could also be described as rgba(251, 16, 16, 1). The red value, 251, is far higher than the green and blue values (16 and 16), as the color is mostly comprised of red information. 

The alpha value of 1 means that it is fully opaque, and won’t show anything behind what the color is applied to. If we change the alpha value to be 0.5, the color will be 50% transparent. If you use an rgb() function instead of rgba(), you don’t have to supply an alpha value. This creates terser code, but prevents you from using transparency.

CodePen Embed Fallback hsl() and hsla()

Similar to rgb() and rgba(), hsl() and hsla() are functions that allow you to describe color. Instead of using red, green, and blue, they use hue (h), saturation (s), and lightness (l). 

I prefer using hsla() over rgba() because its model of describing color works really well with systematized color systems. Each of the color level values for these functions can be CSS Custom Properties, allowing you to create powerful, dynamic code.

CodePen Embed Fallback Syntax updates

In the upcoming CSS Color Module Level 4 spec, we can ignore the a portion of rgba() and hsla(), as well as the commas. Now, spaces are used to separate the rgb and hsl arguments, with an optional / to indicate an alpha level.

https://twitter.com/argyleink/status/1218305696862588928 Pseudo Class Selectors

These selectors use specialized argument notation that specifies patterns of what to select. This allows you to do things like select every other element, every fifth element, every third element after the seventh element, etc.

Pseudo class selectors are incredibly versatile, yet often overlooked and under-appreciated. Many times, a thoughtful application of a few of these selectors can do the work of one or more node packages. 

:nth-child()

nth-child() allows you to target one or more of the elements present in a group of elements that are on the same level in the Document Object Model (DOM) tree.

In the right hands, :nth-child() is incredibly powerful. You can even solve fizzbuzz with it! If you’re looking for a good way to get started, Chris has a collection useful pseudo selector recipes.

:nth-last-child()

This pseudo class selector targets elements in a group of one or more elements that are on the same level in the DOM. It starts counting from the last element in the group and works backwards through the list of available DOM nodes.

CodePen Embed Fallback :nth-last-of-type()

This pseudo class selector can target an element in a group of elements of a similar type. Much like :nth-last-child(), it starts counting from the last element in the group. Unlike :nth-last-child, it will skip elements that don’t apply as it works backwards. 

CodePen Embed Fallback :nth-of-type()

:nth-of-type() matches a specified collection of elements of a given type. For example, a declaration of img:nth-of-type(5) would target the fifth image on a page.

CodePen Embed Fallback Animation Functions

Animation is an important part of adding that certain je ne sais quoi to your website or web app. Just remember to put your users’ needs first and honor their animation preferences.

Creating animations also requires controlling the state of things over time, so functions are a natural fit for making that happen.

cubic-bezier()

Instead of keyword values like ease, ease-in-out, or linear, you can use cubic-bezier() to create a custom timing function for your animation. While you can read about the math that powers cubic beziers, I think it’s much more fun to play around with making one instead.

Lea Verou’s cubic-bezier.com. path()

This function is paired with the offset-path property. It allows you to “draw” a SVG path that other elements can be animated to follow.

CodePen Embed Fallback

Both Michelle Barker and Dan Wilson have published excellent articles that go into more detail about this approach to animation.

steps()

This relatively new function allows you to set the easing timing across an animation, which allows for a greater degree of control over what part of the animation occurs when. Dan Wilson has another excellent writeup of how it fits into the existing animation easing landscape. 

Sizing and Scaling Functions

One common thing we do with animation is stretch and squash stuff. The following functions allow you to do exactly that. There is a catch, however: These CSS functions are a special subset, in that they can only work with the transform property.

scaleX(), scaleY(), scaleZ(), scale3d(), and scale()

Scaling functions let you increase or decrease the size of something along one or more axes. If you use scale3d() you can even do this in three dimensions!

translateX(), translateY(), translateZ(), translate3d(), and translate()

Translate functions let you reposition an element along one or more axes. Much like scale functions, you can also extend this manipulation into three dimensions.

perspective()

This function lets you adjust the appearance of an object to make it look like it is projecting up and out from its background.

rotateX(), rotateY(), rotateZ(), rotate3d(), and rotate()

Rotate functions let you swivel an element along one or more axes, much like grasping a ball and turning it around in your hand.

skewX(), skewY(), and skew()

Skew functions are a little different from scaling and rotation functions in that they apply a distortion effect relative to a single point. The amount of distortion is proportionate to the angle and distance declared, meaning that the further the effect continues in a direction the more pronounced it will be. 

Jorge Moreno also did us all a favor and made a great tool called CSS Transform Functions Visualizer. It allows you to adjust sizing and scaling in real time to better understand how all these functions work together:

As responsible web professionals, we should be mindful of our users and the fact that they may not be using new or powerful hardware to view our content. Large and complicated animations may slow down the experience, or even cause the browser to crash in extreme scenarios.

To prevent this, we can use techniques like will-change to prepare the browser for what’s in store, and the update media feature to remove animation on devices that do not support a fast refresh rate. 

Filter Functions

CSS filter functions are another special subset of CSS functions, in that they can only work with the filter property. Filters are special effects applied to an element, mimicking functionality of graphics editing programs such as Photoshop.

You can do some really wild things with CSS filter functions, stuff like recreating the effects you can apply to your posts on Instagram!

brightness()

This function adjusts how, um, bright something appears. Setting it to a low level will make it appear as if it has had a shadow cast over it. Setting it to a high level will blow it out, like an over-exposed photo.

CodePen Embed Fallback blur()

If you’re familiar with Photoshop’s Gaussian Blur filter, you know how blur() works. The more of this you apply, the more indistinct the thing you apply it to will look.

CodePen Embed Fallback contrast()

contrast() will adjust the degree of difference between the lightest and darkest parts of what is applied to.

CodePen Embed Fallback grayscale()

grayscale() removes the color information from what it is applied to. Remember that this isn’t an all-or-nothing affair! You can apply a partial grayscale effect to make something look weathered or washed out.

CodePen Embed Fallback

An interesting application of grayscale() could be lightly applying it to images when dark mode is enabled, to slightly diminish the overall vibrancy of color in a situation where the user may want less eye strain.

invert()

While invert() can be used to make something look like a photo negative, my favorite technique is to use it in a inverted colors media query to invert inverted images and video:

@media (inverted-colors: inverted) {   img,   video {     filter: invert(100%);   } }

This ensures that image and video content looks the way it should, regardless of a user’s expressed browsing mode preferences. 

opacity()

This function controls how much of the background is visible through the element (and child elements) the function is applied to. 

CodePen Embed Fallback

An element that has 0% opacity will be completely transparent, although it will still be present in the DOM. If you need to remove an object completely, use other techniques such as the hidden attribute.

saturate()

Applying this filter can enhance, or decrease the intensity of the color of what it is applied to. Enhancing an image’s saturation is a common technique photographers use to fix underexposed photos.

CodePen Embed Fallback

sepia()

There are fancier ways to describe this, but realistically it’s a function that makes something look like it’s an old-timey photograph.

CodePen Embed Fallback

drop-shadow()

A drop shadow is a visual effect applied to an object that makes it appear like it is hovering off of the page. There’s a bit of a trick here, in that CSS also allows you to apply drop shadow effects to text and elements. It’s also distinct from the box-shadow property is that it applies drop shadows to the shape of an element rather than the actual box of an element.

Skilled designers and developers can take advantage of this to create complicated visual effects.

CodePen Embed Fallback

hue-rotate()

When a class with a declaration containing hue-rotate() is applied to an element, each pixel used to draw that element will have it’s hue valued shifted by the amount you specify. hue-rotate()‘s effect is applied to each and every pixel it is applied to, so all colors will update relative to their hue value’s starting point.

This can create a really psychedelic effect when applied to things that contain a lot of color information, such as photos.

CodePen Embed Fallback

SVG filters 

filter() also lets us import SVGs filters to use to create specialized visual effects. The topic is too complicated to really do it justice in this article — if you’re looking for a good starting point, I recommend “The Art Of SVG Filters And Why It Is Awesome” by Dirk Weber.

This effect was created by skillful application of SVG filter effects. Gradient Functions

Gradients are created when you transition one color to one or more other colors. They are workhorses of modern user interfaces — skilled designers and developers use them to lend an air of polish and sophistication to their work.

Gradient functions allow you to specify a whole range of properties, including:

  • Color values,
  • The position on the gradient area where that color comes in,
  • What angle the gradient is positioned at.

And yes, you guessed it: the colors we use in a gradient can be described using CSS color functions!

linear-gradient() and repeating-linear-gradient()

Linear gradients apply the color transformation in a straight line, from one point to another — this line can be set at an angle as well. In cases where there’s more area than gradient, using repeating-linear-gradient() will, er, repeat the gradient you described until all the available area has been filled.

CodePen Embed Fallback radial-gradient() and repeating-radial-gradient()

Radial gradients are a lot like linear gradients, only instead of a straight line, color transformations radiate outward from a center point. They’re oftentimes used to create a semitransparent screen to help separate a modal from the background it is placed over.

CodePen Embed Fallback conic-gradient() and repeating-conical-gradient

Conic gradients are different from radial gradients in that the color rotates around a circle. Because of this, we can do neat things like create donut charts. Unfortunately, support for conic gradients continues to be poor, so use them with caution.

An adjustable conic gradient donut chart made by Ana Tudor Grid Functions

CSS Grid is a relatively new feature of the language. It allows us to efficiently create adaptive, robust layouts for multiple screen sizes. 

It’s worth acknowledging our roots. Before Grid, layout in CSS was largely a series of codified hacks to work with a language originally designed to format academic documents. Grid’s introduction is further acknowledgement that the language’s intent has changed. 

Modern CSS is an efficient, fault-tolerant language for controlling presentation and layout across a wide range of device form factors. Equipped with Grid and other properties like flexbox, we’re able to create layouts that would have been impossible to create in earlier iterations of CSS. 

Grid introduces the following CSS functions to help you use it.

fit-content()

This function “clamps” the size of grid rows or columns, letting you specify a maximum size a grid track can expand to. fit-content() accepts a range of values, but most notable among them are min-content and max-content. These values allow you to tie your layout to the content it contains. Impressive stuff!

CodePen Embed Fallback minmax()

minmax() allows you to set the minimum and maximum desired heights and widths of your grid rows and columns. This function can also use min-content and max-content, giving us a great deal of power and flexibility.

CodePen Embed Fallback repeat()

You can loop through patterns of grid column and rows using repeat(). This is great for two scenarios: 

  1. When you do know how many rows or columns you need, but typing them out would be laborious. A good example of this would be constructing the grid for a calendar.
  2. When you don’t know how many rows or columns you need. Here, you can specify a template that the browser will honor as it propagates content into your layout.
CodePen Embed Fallback Shape Functions

Like filter() and transform(), shape CSS functions only work with one property: clip-path. This property is used to mask portions of something, allowing you to create all sorts of cool effects.

circle()

This function creates a circular shape for your mask, allowing you to specify its radius and position.

CodePen Embed Fallback ellipse()

Like circle(), ellipse() will draw a rounded shape, only instead of a perfect circle, ellipse() lets you construct an oblong mask.

CodePen Embed Fallback inset()

This function will mask out a rectangle inside of the element you apply it to.

CodePen Embed Fallback

polygon()

With polygon(), you are able to specify an arbitrary number of points, allowing you to draw complicated shapes. polygon() also takes an optional fill-rule argument, which specifies which part of the shape is the inside part.

CodePen Embed Fallback Miscellaneous Functions

These are the un-categorizable CSS functions, things that don’t fit neatly elsewhere.

element()

Ever pointed a camera at its own video feed? That’s sort of what element() does. It allows you to specify the ID of another element to create an “image” of what that element looks like. You can then apply other CSS to that image, including stuff like CSS filters!

It might take a bit to wrap your head around the concept — and it has some support concerns — but element() is a potentially very powerful in the right hands.

Preethi Sam‘s “Using the Little-Known CSS element() Function to Create a Minimap Navigator” demonstrates how to use it to create a code minimap and is an excellent read.

Here, she’s created a minimap for reading through a longform article:

CodePen Embed Fallback image-set()

This function allows you to specify a list of images for the browser to select for a background image, based on what it knows about the capabilities of its display and its connection speed. It is analogous to what you would do with the srcset property.

::slotted()

This is a pseudo-element selector used to target elements that have been placed into a slot inside a HTML template. ::slotted() is intended to be used when working with Web Components, which are custom, developer-defined HTML elements.

Not Ready for Prime Time

Like any other living programming language, CSS includes features and functionality that are actively being worked on. 

These functions can sometimes be previewed using browsers that have access to the bleeding edge. Firefox Nightly and Chrome Canary are two such browsers. Other features and functionality are so new that they only exist in what is being actively discussed by the W3C.

annotation()

This function enables Alternate Annotation Forms, characters reserved for marking up things like notation and annotation. These characters typically will be outlined with a circle, square, or diamond shape.

Not many typefaces contain Alternate Annotation Forms, so it’s good to check to see if the typeface you’re using includes them before trying to get annotation() to work. Tools such as Wakamai Fondue can help with that.

Examples of annotation glyphs from Jonathan Harrell’s post, “Better Typography with Font Variants” counter() and counters()

When you create an ordered list in HTML, the browser will automatically generate numbers for you and place them before your list item content. These pieces of browser-generated list content are called counters. 

By using a combination of the ::marker pseudo-element selector, the content property, and the counter() function, we can control the content and presentation of the counters on an ordered list. For browsers that don’t support counter() or counters() yet, you still get a decent experience due to the browser automatically falling back to its generated content:

CodePen Embed Fallback

For situations where you have nested ordered lists, the counters() function allows a child ordered list to access its parent. This allows us to control their content and presentation. If you want to learn more about the power of ::marker, counter(), and counters(), you can read “CSS Lists, Markers, And Counters” by Rachel Andrew.

cross-fade()

This function will allow you to blend one background image into one or more other background images. Its proposed syntax is similar to gradient functions, where you can specify the stops where images start and end.

dir()

This function allows you to flip the orientation of a language’s reading order. For English, that means a left-to-right (ltr) reading order gets turned into right-to-left (rtl). Only Firefox currently has support for dir(), but you can achieve the same effect in Chromium-based browsers by using an attribute selector such as [dir="rtl"].

CodePen Embed Fallback env()

env(), short for environment, allows you to create conditional logic that is triggered if the device’s User Agent matches up. It was popularized by the iPhone X as a method to work with its notch

That being said, device sniffing is a fallacious affair — you shouldn’t consider env() a way to cheat it. Instead, use it as intended: to make sure your design works for devices that impose unique hardware constraints on the viewport.

has()

has() is a relational pseudo-class that will target an element that contains another element, provided there is at least one match in the HTML source. An example of this is be a:has(> img), which tells the browser to target any link that contains an image. 

Interestingly, has() is currently being proposed as CSS you can only write in JavaScript. If I were to wager a guess as to why this is, it is to scope the selector for performance reasons. With this approach has() is triggered only after the browser has been told to process conditional logic, and therefore query the state of things.

image()

This function will let you insert either a static image (referenced with url(), or draw one dynamically via gradients and element(). 

Trigonometry functions

These functions will allow us to perform more advanced mathematical operations

  • Sine: sin()
  • Cosine: cos()
  • Tangent: tan()
  • Arccosine: acos()
  • Arcsine: asin()
  • Arctangent: atan()
  • Arctangent: atan2()
  • Square root: sqrt()
  • The square root of the sum of squares of its arguments: hypot()
  • Power: pow()

I’m especially excited to see what people who are more clever than I am will do with these functions, especially for things like animation!

clamp()

When providing minimum, maximum, and preferred values as arguments, clamp() will honor the preferred value so long as it does not exceed the minimum and maximum boundaries. 

clamp() will allow us to author things like components whose size will scale along with the size of the viewport, but won’t shrink or grow past a specific size. This will be especially useful for creating CSS locks, where you can ensure a responsive type size will not get so small that it can’t be read.

:host() and :host-context()

To be honest, I’m a little hazy on the specifics of the jargon and mechanics that power the Shadow DOM. Here’s how the MDN describes host():

The :host() CSS pseudo-class function selects the shadow host of the shadow DOM containing the CSS it is used inside (so you can select a custom element from inside its shadow DOM) — but only if the selector given as the function’s parameter matches the shadow host.

And here’s what they have to say about :host-context():

The :host-context() CSS pseudo-class function selects the shadow host of the shadow DOM containing the CSS it is used inside (so you can select a custom element from inside its shadow DOM) — but only if the selector given as the function’s parameter matches the shadow host’s ancestor(s) in the place it sits inside the DOM hierarchy.

:is() and :where()

:is() has had a bit of an identity crisis. Previously referred to as both matches() and vendor prefixed as :-webkit-any/:-moz-any, it now enjoys a standardized, agreed-upon name. It is a pseudo class selector that accepts a range of selectors as its argument. 

This allows an author to group and target a wide range of selectors in an efficient way. :where() is much like :is(), only it has a specificity of zero, while the specificity of :is() is set to the highest specificity in the provided selector list. 

:is() and :where() will allow us a good deal of flexibility about how we select things to style, especially for situations where you may not have as much control over the web site or web app’s stylesheet (e.g. third-party integrations, ads, etc.).

https://twitter.com/argyleink/status/1192562385489260544 max() and min()

These functions allow you to select either the maximum or minimum value from a range of values you provide. Much like clamp(), these functions allow us to make things responsive up until a certain point. 

:nth-col() and :nth-last-col()

These pseudo-classes will allow you to select one or a specified series columns in a CSS grid to apply styling to them. A good mental model for how these functions will work is how CSS pseudo class selectors operate. Unlike pseudo class selectors, :nth-col() and :nth-last-col() should be able to target implicit grid columns.

symbols()

This function allows you to specify a list of different kinds of characters to use for list bullets. Much like annotation(), you’ll want to make sure the typeface you use contains a glyph you want to use as a symbol before trying to get symbols() to work.

Deprecated Functions

Sometimes things just don’t work out the way you think they will. While deprecated CSS functions may still render in the browser for legacy support reasons, it isn’t recommended you use them going forward.

matrix() and matrix3d()

These functions were turned into more discrete sizing and scaling functions.

rect()

This function was part of the deprecated clip property. Use the clip-path property and its values instead.

target-counter(), target-counters(), and target-text()

These functions were intended to help work with fragment URLs for paged (printed) media. You can read more about them on the W3C’s CSS Generated Content for Paged Media Module documentation

Typography

The web is typography, so it makes sense to give your type the care and attention it deserves. While CSS provides some functions specifically designed to unlock the potential of your website or webapp’s chosen typefaces, it is advised to not use the following functions to access these advanced features. 

Instead, use lower-level syntax via font-feature-settings. You can figure out if the font you’re using supports these features by using a  tool such as Wakamai Fondue.

character-variant(), styleset(), and stylistic()

Many typefaces made by professional foundries include alternate treatments for certain letters, or combinations of letters. One example use case is providing different variations of commonly-used letters for typefaces designed to look like handwriting, to help make it appear more natural-looking.

Stylistic Alternates example by Tunghsiao Liu’s “OpenType Features in CSS”

Utilizing these functions activates these special alternate characters, provided they are present in the font’s glyph set

Unfortunately, it is not a standardized offering. Different typefaces will have different ranges of support, based on what the typographer chose to include. It would be wise to check to see if the font you’re using supports these special features before writing any code.

format()

When you are importing a font via the url() function, the format() function is an optional hint that lets you manually specify the font’s file format. If this hint is provided, the browser won’t download the font if it does not recognize the specified file format.

@font-face {   font-family: 'MyWebFont';   src: url('mywebfont.woff2') format('woff2'), /* Cutting edge browsers */        url('mywebfont.woff') format('woff'), /* Most modern Browsers */        url('mywebfont.ttf') format('truetype'); /* Older Safari, Android, iOS */ } leader()

You know when you’re reading a menu at a restaurant and there’s a series of periods that help you figure out what price is attached to what menu item? Those are leaders. 

The W3C had plans for them with its CSS Generated Content for Paged Media Module, but it unfortunately seems like leader() never quite managed to take off. Fortunately, the W3C also provides an example of how to accomplish this effect using a clever application of the content property.

local()

local() allows you to specify a font installed locally, meaning it is present on the device. Local fonts either ship with the device, or can be manually installed. 

Betting on someone installing a font so things look the way you want them to is very risky! Because of this, it is recommended you don’t specify a local font that needs to be manually installed. Your site won’t look the way it is intended to, even moreso if you don’t specify a fallback font.

@font-face { font-family: 'FeltTipPen'; src: local('Felt Tip Pen Web'), /* Full font name */ local('FeltTipPen-Regular'); /* Postscript name */ } ornaments()

Special dingbat characters can be enabled using this function. Be careful, as not all dingbat characters are properly coded in a way that will work well if a user does something like change the font, or use a specialized browsing mode.

swash()

Swashes are alternate visual treatments for letters that give them an extra-fancy flourish. They’re commonly found in italic and cursive-style typefaces.

Swash example by Tunghsiao Liu’s “OpenType Features in CSS” Why so many?

CSS is maligned as frequently as it is misunderstood. The guiding thought to understanding why all these functions are made available to us is knowing that CSS isn’t prescriptive — not every website has to look like a Microsoft Word document. 

The technologies that power the web are designed in such a way that someone with enough interest can build whatever they want. It’s a powerful, revolutionary concept, a large part of why the web became so ubiquitous.

The post A Complete Guide to CSS Functions appeared first on CSS-Tricks.

No-Comma Color Functions in CSS

Css Tricks - Mon, 05/04/2020 - 4:48am

There have been a couple of viral tweets about this lately, one from Adam Argyle and one from Mathias Bynes. This is a nice change that makes CSS a bit more clear. Before, every single color function actually needs two functions, one for transparency and one without, this eliminates that need and brings the syntax more-inline with CSS grammar overall.

Lemme remake the code blocks from Mathias’ tweet here:

/* Old Syntax */ rgb(0, 128, 255) rgba(0, 128, 255, 0.5) hsl(198, 38% 50%) hsla(198, 28%, 50%, 0.5) /* New Syntax */ rgb(0 128 255) rgb(0 128 255 / 50%) hsl(198deg 28% 50%) hsl(198deg 28% 50% / 50%) lab(56.29% -10.93 16.58 / 50%) lch(56.29% 19.86 236.62 / 50%) color(sRGB 0 0.50 1 / 50%)

Thought party:

  • The browser support is pretty good: everything but IE 11.
  • If you need IE 11 support, you can preprocess it (or not use it). PostCSS’s preset-env does it as well as the very specific plugin postcss-color-rgb (weird it doesn’t do HSL also).
  • If you don’t like it, you literally never need to use it. No browser will ever pull support for such an important feature.
  • The reason to switch is muscle memory and consistent-looking codebases as new color functions (e.g, lab, lch, and color) will only support this new syntax.
  • There is a weird hybrid between old and new. You can pass an opacity value to rgb() and it still works like rgb(255, 0, 0, 0.5);.
  • If you need it in Sass (which is apparently a pain to support), there is a weird workaround. I would guess Sass will get around to supporting it. If they can’t, this is the kind of barb that drives people away from projects.
  • Prettier, which is in the business of cleaning up your code from the perspective of spacing and syntax, could intervene here and convert syntax, but it’s not going to (the Prettier stance is to not change the AST).
  • I imagine DevTools will start showing colors in this format, which will drive adoption.
  • Remember even hex code colors have a fancy new format.

The post No-Comma Color Functions in CSS appeared first on CSS-Tricks.

Creating a Gauge in React

Css Tricks - Sun, 05/03/2020 - 3:45am

You should really look at everything Amelia does, but I get extra excited about her interactive blog posts. Her latest about creating a gauge with SVG in React is unreal. Just the stuff about understanding viewBox is amazing and that’s like 10% of it.

Don’t miss her earlier posts like the one on CSS Cascade or React Hooks either.

Direct Link to ArticlePermalink

The post Creating a Gauge in React appeared first on CSS-Tricks.

Phuoc Nguyen’s One Page Wonders

Css Tricks - Sat, 05/02/2020 - 3:42am

I keep running across these super useful one page sites, and they keep being by the same person! Like this one with over 100 vanilla JavaScript DOM manipulation recipes, this similar one full of one-liners, and this one with loads of layouts. For that last one, making 91 icons for all those design patterns is impressive alone. High five, Phuoc.

This is my favorite sort of marketing. Some of the products aren’t free, like the React PDF Viewer. How do you get people to know about your paid thing? Give a bunch of useful stuff away for free and have the paid thing sitting right next to it.

The post Phuoc Nguyen’s One Page Wonders appeared first on CSS-Tricks.

Enable Gatsby Incremental Builds on Netlify

Css Tricks - Fri, 05/01/2020 - 5:17am

The concept of an “incremental build” is that, when using some kind of generator that builds all the files that make for a website, rather than rebuilding 100% of those files every single time, it only changes the files that need to be changed since the last build. Seems like an obviously good idea, but in practice I’m sure it’s extremely tricky. How do you know what exactly which files will change and which won’t before building?

I don’t have the answer to that, but Gatsby has it figured out. Faster local builds is half the joy, the other half is that deployment also becomes faster, as the files that need to move around are far fewer.

I’d say incremental builds are a pretty damn big deal. I like seeing these hurdles get cleared Jamstack-land. I’m linking to the Netlify blog post here as getting it going on Netlify requires you to enable their “build plugins” feature which is also a real ahead-of-the-game feature, allowing you to run code during different parts of CI/CD with a really clean syntax.

Direct Link to ArticlePermalink

The post Enable Gatsby Incremental Builds on Netlify appeared first on CSS-Tricks.

The Hero Generator

Css Tricks - Thu, 04/30/2020 - 11:37am

Sarah:

I’ve had to implement the same hero for several years now, so like a good lazy programmer, I figured I’d automate it.

Direct Link to ArticlePermalink

The post The Hero Generator appeared first on CSS-Tricks.

CSS-Tricks Chronicle XXXVIII

Css Tricks - Thu, 04/30/2020 - 9:29am

Hey hey, these “chronicle” posts are little roundups of news that I haven’t gotten a chance to link up yet. They are often things that I’ve done off-site, like be a guest on a podcast or online conference. Or it’s news from other projects I work on. Or some other thing I’ve been meaning to shout out. Stuff like that! Enjoy the links!

I chatted with Paul Campbell the other day during Admission Online, an online conference put together by the Tito crew . They’ve published all the videos there including mine.

I had a chance to chat with Paul about his Tito service about last year on ShopTalk in a really great episode. Tito is a best-in-class software tool for running a conference. It helps you build a site, sell tickets, manage attendees, run reports, and all that. Clearly the COVID-19 situation has impacted that business a lot, so I admire the accelerated pivot they are doing by creating Vito, a new platform for running online conferences, and running these conferences super quickly as a way to showcase it. If you’re running an online conference, I’d get on that invite list ASAP.

Jina Anne has been doing something new as well in the online event space. She’s been doing these 30-minute AMA (Ask Me Anything) sessions with interesting folks (excluding me). Upcoming events are here. They are five bucks, and that gets you live access and the ability to actually ask a question. Jina publishes past events to YouTube. Here’s one with me:

I was interviewed on Balance the Grid. Here’s one exchange:

What do you think are some of the best habits or routines that you’ve developed over the years to help you achieve success in your life?

I’m quite sure I have more bad habits than good, so take all this with a bucket of salt. But one thing I like to do is to try to make as much of the time I spend working is spent working on something of lasting value.

That’s why I like to blog, for example. If I finish a blog post, that’s going to be published at a URL and that URL is going to get some traffic now, and at least a little bit of traffic forever. The more I do that the more I build out my base of lasting content that will serve me forever.

Over at CodePen, we’ve been busier than ever working toward our grand vision of what CodePen can become. We have a ton of focus on things lately, despite this terrible pandemic. It’s nice to be able to stay heads down into work you find important and meaningful in the best of times, and if that can be a mental escape as well, well, I’ll take it.

We’ve been building more community-showcasing features. On our Following page there are no less than three new features: (1) A “Recent” feed¹, (2) a “Top” feed, and (3) Follow suggestions. The Following page should be about 20× more interesting by my calculation! For example, the recent feed is the activity of all the people you follow, surfacing things you likely won’t want to miss.

You can toggle that feed from “Recent” over to “Top.” While that seems like a minor change, it’s actually an entirely different feed that we create that is like a ranked popularity feed, only scoped to people you follow.

Below that is a list of other recommended CodePen folks to follow that’s created just for you. I can testify that CodePen is a lot more fun when you follow people that create things you like, and that’s a fact we’re going to keep making more and more true.

We’re always pushing out little stuff, but while I’m focusing on big new things, the biggest is the fact that we’ve taken some steps toward “Custom Editors.” That is, Pen Editors that can do things that our normal Pen Editor can’t do. We’ve released two: Flutter and Vue Single File Components.

  1. The word “feed” is new. We don’t actually use that term on the site. It’s a word we use internally on the team and what’s used by the technology we’re using. But I think it’s a good general description for the CodePen community as well, since CodePen is a developer-facing site anyway. I suppose “stream” is also a good descriptor (and just so happens to be the literal name of the tech we’re using.

This is about the time of year I would normally be telling you about the Smashing Conference I went to and the wonderful time I had there, but those in-person conferences have, of course, been re-scheduled for later in the year. At the moment, I’m still planning on Austin in October and San Francisco in November, but of course, nobody knows what the world will be like then. One thing is for sure though: online workshops. Smashing has been doing lots of these, and many of them are super deep courses that take place over several weeks.

Lots of conferences are going online and that’s kinda cool to see. It widens the possibility that anyone in the world can join, which is the web at its best. Conferences like All Day Hey are coming up in a few weeks (and is only a handful of bucks). Jamstack Conf is going virtual in May. My closest-to-home conference this year, CascadiaJS, is going virtual in September.

I got to be on the podcast Coding Zeal. I can’t figure out how to embed a BuzzSprout episode, so here’s a link.

The post CSS-Tricks Chronicle XXXVIII appeared first on CSS-Tricks.

Real-World Effectiveness of Brotli

Css Tricks - Thu, 04/30/2020 - 4:34am

Harry Roberts:

The numbers so far show that the difference between no compression and Gzip are vast, whereas the difference between Gzip and Brotli are far more modest. This suggests that while the nothing to Gzip gains will be noticeable, the upgrade from Gzip to Brotli might perhaps be less impressive.

The rub?

Gzip made files 72% smaller than not compressing them at all, but Brotli only saved us an additional 5.7% over that. In terms of FCP, Gzip gave us a 23% improvement when compared to using nothing at all, but Brotli only gained us an extra 3.5% on top of that.

So Brotli is just like spicy gzip.

Still, I’ll take a handful of points by flipping a switch in Cloudflare.

Direct Link to ArticlePermalink

The post Real-World Effectiveness of Brotli appeared first on CSS-Tricks.

A Book Apart Turning 10

Css Tricks - Thu, 04/30/2020 - 3:28am

Early congratulations, A Book Apart! That’s a hell of a milestone. I’m quite sure I’ve read more A Book Apart books than any other tech book publisher.

Katel LeDu runs the ship over there, and she’s given me very special pack of discount codes that will get you my book, Practical SVG, for free. So now it’s my job to get you those codes. There are only 10 of them—not enough for everyone. So I’m going to do some low-down, dirty-rotten, absolutely-shameless cross-marketing: I’m going to give them to the first 10 people who are CodePen PRO who email me at chriscoyier@gmail.com. CodePen PRO is only $12/month if you pay monthly or $8/month if you pay yearly, and this discount code is worth $14, so in the end, you get both and save a few bucks. If you’re already PRO, cool, thanks, you still qualify.

You know what’s cool about Practical SVG? Even though I wrote it 4 years ago, SVG just doesn’t change that fast, so I’d say 90%+ I wouldn’t even change in a re-write. If you’re just learning about SVG as a front-end developer, it’s a fine choice.

In addition to my conniving scheme above, if you just really would like this book and have zero budget for it, or know someone else in that situation, you can also email me about that and we’ll work it out. I just may have a few copies around here I could get you. Hey, I’m trying to make money off you but I ain’t trying to lock away knowledge from anyone that really needs it.

The post A Book Apart Turning 10 appeared first on CSS-Tricks.

Click Once, Select All; Click Again, Select Normally

Css Tricks - Wed, 04/29/2020 - 11:17am

A bonafide CSS trick from Will Boyd!

  1. Force all the content of an element to be selected when clicked with user-select: all;
  2. If you click a second time, let the user select just parts of the text as normal.
  3. Second click? Well, it’s a trick. You’re really using a time-delayed forwards-ending @keyframes animation when the element is in :focus to change it to user-select: text;
CodePen Embed Fallback

Will’s article has a bunch of more useful information and use-cases for user-select.

Direct Link to ArticlePermalink

The post Click Once, Select All; Click Again, Select Normally appeared first on CSS-Tricks.

[David Baron’s] Thoughts on an implementable path forward for Container Queries

Css Tricks - Wed, 04/29/2020 - 5:50am

That’s the title of a public post from David Baron, a Principal Engineer at Firefox, with thoughts toward container queries. I know a lot of people have been holding their breath waiting for David’s ideas, as he’s one of few uniquely qualified to understand the ins and outs of this and speak to implementation possibility.

We’re still in the early stages of container queries. Every web designer and developer wants them, the browsers know it, but it’s a super complicated situation. It was very encouraging in February 2020 to hear positive signals about a possible switch-statement syntax that would give us access to an available-inline-size used to conditionally set individual values.

Now we’re seeing a second idea that is also in the realm of the possible.

This ideas uses an @rule instead for the syntax. From the document:

@container <selector> (<container-media-query>)? { // ... rules ... }

So I’m imagining it like:

.parent { contain: layout inline-size; display: grid; grid-template-columns: 100%; gap: 1rem; } @container .parent (min-width: 400px) { grid-template-columns: 1fr 1fr; .child::before { content: "Hello from container query land!"; } }

Except…

  1. I’m not sure if you’d have to repeat the selector inside as well? Or if dropping property/value pairs in there automatically applies to the selector in the @rule.
  2. David says, “The rules can match only that container’s descendants. Probably we’d need support for some properties applying to the container itself, but others definitely can’t.” I’d hope grid properties are a strong contender for something you can change, but I have no idea. Otherwise, I think we’d see people wrapping elements with <div class="container-query"> to get around the “only descendants” limit.

Containment seems to be a very important part of this. Like, if the element isn’t property contained, the container query just won’t work. I don’t know that much about containment, but Rachel has a great deep dive from late last year.

Again, this is super early days, I’m just having fun watching this and none of us really have any idea what will actually make it to browsers.

Direct Link to ArticlePermalink

The post [David Baron’s] Thoughts on an implementable path forward for Container Queries appeared first on CSS-Tricks.

Alpine.js: The JavaScript Framework That’s Used Like jQuery, Written Like Vue, and Inspired by TailwindCSS

Css Tricks - Wed, 04/29/2020 - 4:50am

We have big JavaScript frameworks that tons of people already use and like, including React, Vue, Angular, and Svelte. Do we need another JavaScript library? Let’s take a look at Alpine.js and you can decide for yourself. Alpine.js is for developers who aren’t looking to build a single page application (SPA). It’s lightweight (~7kB gzipped) and designed to write markup-driven client-side JavaScript.

The syntax is borrowed from Vue and Angular directive. That means it will feel familiar if you’ve worked with those before. But, again, Alpine.js is not designed to build SPAs, but rather enhance your templates with a little bit of JavaScript.

For example, here’s an Alpine.js demo of an interactive “alert” component.

CodePen Embed Fallback

The alert message is two-way bound to the input using x-model="msg". The “level” of the alert message is set using a reactive level property. The alert displays when when both msg and level have a value.

It’s like a replacement for jQuery and JavaScript, but with declarative rendering

Alpine.js is a Vue template-flavored replacement for jQuery and vanilla JavaScript rather than a React/Vue/Svelte/WhateverFramework competitor.

Since Alpine.js is less than a year old, it can make assumptions about DOM APIs that jQuery cannot. Let’s briefly draw a comparison between the two.

Querying vs. binding

The bulk of jQuery’s size and features comes in the shape of a cross-browser compatibility layer over imperative DOM APIs — this is usually referred to as jQuery Core and sports features that can query the DOM and manipulate it.

The Alpine.js answer to jQuery core is a declarative way to bind data to the DOM using the x-bind attribute binding directive. It can be used to bind any attribute to reactive data on the Alpine.js component. Alpine.js, like its declarative view library contemporaries (React, Vue), provides x-ref as an escape hatch to directly access DOM elements from JavaScript component code when binding is not sufficient (eg. when integrating a third-party library that needs to be passed a DOM Node).

Handling events

jQuery also provides a way to handle, create and trigger events. Alpine.js provides the x-on directive and the $event magic value which allows JavaScript functions to handle events. To trigger (custom) events, Alpine.js provides the $dispatch magic property which is a thin wrapper over the browser’s Event and Dispatch Event APIs.

Effects

One of jQuery’s key features is its effects, or rather, it’s ability to write easy animations. Where we might use slideUp, slideDown, fadeIn, fadeOut properties in jQuery to create effects, Alpine.js provides a set of x-transition directives, which add and remove classes throughout the element’s transition. That’s largely inspired by the Vue Transition API.

Also, jQuery’s Ajax client has no prescriptive solution in Alpine.js, thanks to the Fetch API or taking advantage of a third party HTTP library (e.g. axios, ky, superagent).

Plugins

It’s also worth calling out jQuery plugins. There is no comparison to that (yet) in the Alpine.js ecosystem. Sharing Alpine.js components is relatively simple, usually requiring a simple case of copy and paste. The JavaScript in Alpine.js components are “just functions” and tend not to access Alpine.js itself, making them relatively straightforward to share by including them on different pages with a script tag. Any magic properties are added when Alpine initializes or is passed into bindings, like $event in x-on bindings.

There are currently no examples of Alpine.js extensions, although there are a few issues and pull requests to add “core” events that hook into Alpine.js from other libraries. There are also discussions happening about the ability to add custom directives. The stance from Alpine.js creator Caleb Porzio, seems to be basing API decisions on the Vue APIs, so I would expect that any future extension point would be inspired on what Vue.js provides.

Size

Alpine.js is lighter weight than jQuery, coming in at 21.9kB minified — 7.1kB gzipped — compared to jQuery at 87.6kB minified — 30.4kB minified and gzipped. Only 23% the size!

Most of that is likely due to the way Alpine.js focuses on providing a declarative API for the DOM (e.g. attribute binding, event listeners and transitions).

Bundlephobia breaks down the two

For the sake of comparison, Vue comes in at 63.5kB minified (22.8kB gzipped). How can Alpine.js come in lighter despite it’s API being equivalent Vue? Alpine.js does not implement a Virtual DOM. Instead, it directly mutates the DOM while exposing the same declarative API as Vue.

Let’s look at an example

Alpine is compact because since application code is declarative in nature, and is declared via templates. For example, here’s a Pokemon search page using Alpine.js:

CodePen Embed Fallback

This example shows how a component is set up using x-data and a function that returns the initial component data, methods, and x-init to run that function on load.

Bindings and event listeners in Alpine.js with a syntax that’s strikingly similar to Vue templates.

  • Alpine: x-bind:attribute="express" and x-on:eventName="expression", shorthand is :attribute="expression" and @eventName="expression" respectively
  • Vue: v-bind:attribute="express" and v-on:eventName="expression", shorthand is :attribute="expression" and @eventName="expression" respectively

Rendering lists is achieved with x-for on a template element and conditional rendering with x-if on a template element.

Notice that Alpine.js doesn’t provide a full templating language, so there’s no interpolation syntax (e.g. {{ myValue }} in Vue.js, Handlebars and AngularJS). Instead, binding dynamic content is done with the x-text and x-html directives (which map directly to underlying calls to Node.innerText and Node.innerHTML).

An equivalent example using jQuery is an exercise you’re welcome to take on, but the classic style includes several steps:

  • Imperatively bind to the button click using $('button').click(/* callback */).
  • Within this “click callback” get the input value from the DOM, then use it to call the API.
  • Once the call has completed, the DOM is updated with new nodes generated from the API response.

If you’re interested in a side by side comparison of the same code in jQuery and Alpine.js, Alex Justesen created the same character counter in jQuery and in Alpine.js.

Back in vogue: HTML-centric tools

Alpine.js takes inspiration from TailwindCSS. The Alpine.js introduction on the repository is as “Tailwind for JavaScript.”

Why is that important?

One of Tailwind’s selling points is that it “provides low-level utility classes that let you build completely custom designs without ever leaving your HTML.” That’s exactly what Alpine does. It works inside HTML so there is no need to work inside of JavaScript templates the way we would in Vue or React  Many of the Alpine examples cited in the community don’t even use script tags at all!

Let’s look at one more example to drive the difference home. Here’s is an accessible navigation menu in Alpine.js that uses no script tags whatsoever.

CodePen Embed Fallback

This example leverages aria-labelledby and aria-controls outside of Alpine.js (with id references). Alpine.js makes sure the “toggle” element (which is a button), has an aria-expanded attribute that’s true when the navigation is expanded, and false when it’s collapsed. This aria-expanded binding is also applied to the menu itself and we show/hide the list of links in it by binding to hidden.

Being markup-centric means that Alpine.js and TailwindCSS examples are easy to share. All it takes is a copy-paste into HTML that is also running Alpine.js/TailwindCSS. No crazy directories full of templates that compile and render into HTML!

Since HTML is a fundamental building block of the web, it means that Alpine.js is ideal for augmenting server-rendered (Laravel, Rails, Django) or static sites (Hugo, Hexo, Jekyll). Integrating data with this sort of tooling can be a simple as outputting some JSON into the x-data="{}" binding. The affordance of passing some JSON from your backend/static site template straight into the Alpine.js component avoids building “yet another API endpoint” that simply serves a snippet of data required by a JavaScript widget.

Client-side without the build step

Alpine.js is designed to be used as a direct script include from a public CDN. Its developer experience is tailored for that. That’s why it makes for a great jQuery comparison and replacement: it’s dropped in and eliminates a build step.

While it’s not traditionally used this way, the bundled version of Vue can be linked up directly. Sarah Drasner has an excellent write-up showing examples of jQuery substituted with Vue. However, if you use Vue without a build step, you’re actively opting out of:

  • the Vue CLI
  • single file components
  • smaller/more optimized bundles
  • a strict CSP (Content Security Policy) since Vue inline templates evaluate expressions client-side

So, yes, while Vue boasts a buildless implementation, its developer experience is really depedent on the Vue CLI. That could be said about Create React App for React, and the Angular CLI. Going build-less strips those frameworks of their best qualities.

There you have it! Alpine.js is a modern, CDN-first  library that brings declarative rendering for a small payload — all without the build step and templates that other frameworks require. The result is an HTML-centric approach that not only resembles a modern-day jQuery but is a great substitute for it as well.

If you’re looking for a jQuery replacement that’s not going to force you into a SPAs architecture, then give Alpine.js a go! Interested? You can find out more on Alpine.js Weekly, a free weekly roundup of Alpine.js news and articles.

The post Alpine.js: The JavaScript Framework That’s Used Like jQuery, Written Like Vue, and Inspired by TailwindCSS appeared first on CSS-Tricks.

How to Redirect a Search Form to a Site-Scoped Google Search

Css Tricks - Tue, 04/28/2020 - 12:10pm

This is just a tiny little trick that might be helpful on a site where you don’t have the time or desire to build out a really good on-site search solution. Google.com itself can perform searches scoped to one particular site. The trick is getting people there using that special syntax without them even knowing it.

Make a search form:

<form action="https://google.com/search" target="_blank" type="GET"> <label> Search CSS-Tricks on Google: <input type="search" name="q"> </label> <input type="submit" value="Go"> </form>

When that form is submitted, we’ll intercept it and change the value to include the special syntax:

var form = document.querySelector("form"); form.addEventListener("submit", function (e) { e.preventDefault(); var search = form.querySelector("input[type=search]"); search.value = "site:css-tricks.com " + search.value; form.submit(); });

That’s all.

CodePen Embed Fallback

The post How to Redirect a Search Form to a Site-Scoped Google Search appeared first on CSS-Tricks.

Static or Not?

Css Tricks - Mon, 04/27/2020 - 11:32am

A quick opinion piece by Kev Quirk: Why I Don’t Use A Static Site Generator. Kev uses WordPress:

Want to blog on my iPad? I can. Want to do it on my phone? No problem. On a machine I don’t normally use? Not an issue, as long as it has a browser.

First, it’s worth understanding that by using WordPress it doesn’t opt you out of using a static site generator. WordPress has an API, and that opens the door to hit that API during a build process and build your site that way. That’s what Gatsby does, there is a plugin that exports a static site, and projects like Frontity really blur the lines.

But I agree with Kev here on his reasoning. For all his reasons, and 1,000 more, it’s a perfectly acceptable and often smart choice to run a WordPress site. I think about it in terms of robustness and feature-readiness. Need e-commerce? It’s there. Need forms? There are great plugins. Need to augment how the CMS works? You have control over the types of content and what is in them. Need auth? That’s a core feature. Wish you had a great editing experience? Gutenberg is glorious.

Time and time again, I build what I want to build with WordPress quickly and efficiently and it makes me feel productive and powerful. But I don’t wanna make this specifically about WordPress; this can be true of any “classic” CMS. Craft CMS has a GraphQL API out of the box. We just posted about a Drupal + Jamstack webinar.

In the relatively new world of static sites, a little thing can end up a journey of research and implementation, like you’re the only third person on Earth to ever do it.

Now all that said…

What do I think of static site generators and the Jamstack world? They are awesome.

I think there is a lot to be said about building sites this way. The decoupling of data and front-end is smart. The security is great. The DX, what with the deploy previews and git-based everything is great. The speed you get out of the gate is amazing (serving HTML from a CDN is some feat).

Just like a classic server-side CMS doesn’t opt you out of building a static site, building with a static site doesn’t opt you out of doing dynamic things — even super duper fancy dynamic things. Josh Comeau has a great new post going into this. He built a fancy little app that does a ton in the browser with React, but that doesn’t mean he still can’t deliver a good amount of it statically. He calls it a “mindset shift,” referring to the idea that you might think you need a database call, but do you really? Could that database call have already happened and generated a static file? And if not, still, some of it could have been generated with the last bits coming over dynamically.

I can’t wait for a world where we start really seeing the best of both worlds. We do as much statically as possible, we get whatever we can’t do that way with APIs, and we don’t compromise on the best tools along the way.

When to go with a static site…
  • If you can, you should consider it, as the speed and security can’t be beaten.
  • If you’re working with a Greenfield project.
  • If your project builds from and uses accessible APIs, you could hit that API during the build process as well as use it after the initial HTML loads.
  • If some static site generator looks like a perfect fit for something you’re doing.
  • If a cost analysis says it would be cheaper.
  • If functionality (like build previews) would be extremely helpful for a workflow.

When to go with server-side software…
  • If you need the features of a classic CMS (e.g. WordPress), and the technical debt of going static from there is too high.
  • If you’re already in deep with a server-rendered project (Ruby on Rails, Python, etc.) and don’t have any existing trouble.
  • If that is where you have the most team expertise.
  • If a cost analytics says it would be cheaper.
  • If there aren’t good static solutions around for what want to build (e.g. forums software).
  • If you have an extreme situation, like millions of URLs, and the build time for static is too high.

Bad reasons to avoid a static site…
  • You need to do things with servers. (Why? You can still hit APIs on servers, either at build or during runtime.)
  • You need auth. (Why? Jamstack is perfectly capable of auth with JWTs and such.)
  • You haven’t even looked into doing things Jamstack-style.
Bad reasons to choose server-side software…
  • You haven’t even looked into doing things Jamstack-style.
  • Because you think using comfortable / existing / classic / well-established / well-supported tools opt you out of building anything statically.
  • Something something SEO. (If anything, statically rendered content should perform better. But it’s understandable if a move to static means moving to client-side calls for something like product data.)

The post Static or Not? appeared first on CSS-Tricks.

Advice for Writing a Technical Resume

Css Tricks - Mon, 04/27/2020 - 4:50am

Marco Rogers asked a very good question on Twitter:

I talk to a lot of people new to tech from non-traditional backgrounds, e.g. bootcamps or self-taught. I'm looking for good information for those people on how to build out a strong resume when they don't have work experience yet. Advice is fine, links to resources is better.

— Marco Rogers (@polotek) April 10, 2020

I’ve been on both sides of the interview table for many years now, both searching for jobs and as a hiring manager. In my years of management, I’ve read though thousands of applications, this article is full of suggestions gleaned from that experience, should it be helpful to you.

When it comes to writing a resume, It’s helpful to think about the human aspect first and foremost. Imagining a hiring manager’s perspective will give you an edge because it helps speak to them directly. Remember, a coveted position at a reputable company commonly requires the team to sift through anywhere between tens and thousands of applications. Their staff is materially impacted in the time and energy it takes to review every candidate and evaluate those who make it in to the interview stage. Attention to details will help your odds of standing out in the crowd.

Here are my general suggestions to make the best possible resume.

Formatting is important

Spelling, grammar and formatting are all crucial to a well-written resume. Typos and errors are clear red flags, so please pay attention to what you write and how it is written. These types of mistakes give the impression that you either lack attention to detail or are unwilling to go the extra step. As trivial as this might seem, it will serve you well to use spell check and get a second set of eyes on your resume before submitting it.

A few formatting tips to keep in mind:

  • Use headings to separate sections
  • Use lists to help summarize highlights and keep things scannable
  • Use a good font and font size that makes the content legible
  • Use line spacing that lets content breathe rather than packing it close together
  • Make good use of bold and italic for pertinent information, but don’t abuse them

I don’t have a strong opinion on charts that show off your skills or lists of hobbies — though, I will say I’ve noticed them more frequently on the applications of beginners. You might unintentionally communicate you have less experience by including it.

If you don’t have a lot of work history, it’s totally OK to throw in open source projects!

Or side projects! Or working on your own site! A few folks mentioned this in the Twitter thread and it’s solid advice. A good hiring manager should know that Senior-level candidates don’t grow on trees — they want to see work that shows you have promise.

This is problematic advice in some ways, as not everyone has time on the side to devote to projects. Including these isn’t a hard requirement for a good resume, but if you’re otherwise lacking relevant work experience, including personal projects can show the kind of work you’re capable of doing as well as the kind of work that excites you. I’ve taken chances on folks with slim-to-no work experience but with a solid portfolio site, GitHub contributions, or even a few CodePen demos that show potential.

Call out your contributions in your work experience

Each time you list a work example, answer this: what did you accomplish? This is a good way to provide valuable information without unnecessary fluff.

Here’s an example that would catch my attention:

Due to my team’s work refactoring the product page, we were able to meet the demands of our customers, which resulted in a 25% growth in sales. We also took the opportunity to upgrade the codebase from React.createClass to React Hooks for all of our components, ensuring a more flexible and maintainable system.

This tells me you can work on a team to deliver goals. It also tells me that you understand technical debt and your part in being proactive in maintenance. That’s the sort of person I want to hire. Write the outcomes from the point of view of what you provided for the team.

If so far your experience is limited to a code bootcamp, it’s great to talk through that.

Every job applicant is coming from a different background and from varying degrees of experience. It’s safe to assume you are not the most experienced person in the pool.

And that’s OK!

For example, let’s say your development experience is limited to online or in-person coding bootcamps rather than commercial projects. What did you learn there? What were you interested in? What was your final project? Is there a link to that work? When I’m hiring someone who’s coming in early in their career, I’m mostly looking for curiosity and enthusiasm. I’m probably not alone there.

Don’t be too long… or too short

We mentioned earlier that hiring is a time-consuming job. It’s good to keep this in mind as you’re writing by making your resume as brief as possible — ideally on a single page. Two pages is OK if you really need it.

Keeping everything short is a balancing act when you’re also attempting to include as much useful information as possible. Treat that constraint as a challenge to focus on the most important details. It’s a good problem if you have more to say than what fits!

At best, padding a resume into multiple pages conveys you’re unable to communicate in a succinct manner. At worst, it shows a lack of respect for a hiring manager’s time.

Make sure there’s a way to reach you

I cannot tell you how many resumes that lack the following essentials: name, email, and phone number. Seriously, it happens even on resumes that are otherwise very impressive.

Your name and contact information are hard requirements. I don’t want to search around for your email if you’re applying. To be honest, I probably won’t search at all because I’m busy and there are many other candidates to choose from.

Preparation is your friend

Make sure your accompanying cover letter (yes, you should include one) communicates you’ve done at least a little research on the company, conveys you understand what they need in a candidate, and how you fit into that need.

I will personally adjust my the descriptions (not the job titles, but the takeaways and outcomes) in my own resume so there is a direct connection between my skills and the position.

Your work and education details should be reverse-chronological

Your most recent work is more important than your oldest work. It’s a better reflection of what you’re capable of doing today and how fresh your skills are in a particular area. The same goes for your education: lead with your most recent experience.

The person reviewing your resume can decide to continue reading further if they’re compelled by the most recent information.

Wrapping up

If you want to stand out in the crowd, make sure your resume is one that represents you well. Ask someone to help you proof and use spellcheck, and make sure you’ve put your best foot forward.

And don’t be discouraged by rejections or unreturned messages. It’s less likely to be about you personally and more likely due to the number of people applying. So keep trying!

The post Advice for Writing a Technical Resume appeared first on CSS-Tricks.

The Cost of Javascript Frameworks

Css Tricks - Sun, 04/26/2020 - 3:30am

I expect this post from Tim Kadlec to be quoted in every performance conference talk for the next few years. There is a lot of data here, so please check it out for yourself, but the short story is that JavaScript-framework-powered sites are definitely heavier and more resource-intensive than non-JavaScript-framework-powered sites. Angular is the beefiest and React is hardest on the CPU. But as Tim says:

… it says very little about the performance of the core frameworks in play and much more about the approach to development these frameworks may encourage

Another big caveat is that there isn’t data here on-site usage after first-load, which is a huge aspect of “single-page app” approaches.

Still, while you can be performant with frameworks (although even that top 10% isn’t super encouraging), the frameworks aren’t doing much to help what has turned into a bad situation. It mimics exactly what we talked about recently with accessibility. It’s not the frameworks “fault” exactly, but they are also the best positioned to stop the bleeding.

Direct Link to ArticlePermalink

The post The Cost of Javascript Frameworks appeared first on CSS-Tricks.

Syndicate content
©2003 - Present Akamai Design & Development.