Author: The tapir

CSS Features you May not Know about 2021

In this topic, I mainly collate features about CSS, and try to collate some properties that you can use now or in the near future. Also, although the title is “New Features,” many of these features are not “new” and may already be in your project, or you’ve seen them but don’t know about them. Next, with you to briefly review these sex, I hope you can like it, also hope to be helpful to your usual work.

CSS proportional scaling

CSS proportional scaling generally refers to “the height of the container is proportional to the width,” often referred to as the aspect ratio or the width ratio. As we all know, the terminals we develop Web pages on are more complex, and they all have different aspect ratios. Common proportions are:

Especially those who are engaged in the development of media, such as videos and images, will have more demands in this respect, such as pictures and video display on Facebook:

Before _aspect-ratio_, CSS often uses some Hacck method to achieve a similar effect, that is, using the padding-top or padding-bottom to achieve:

<aspectratio-container> <aspectratio-content></aspectratio-content> </aspectratio-container> <style> .aspectratio-container { width: 50vmin; /* display: flex; /* display: flex; justify-content: center; align-items: center; / /.aspectratio-container::after {content: ""; width: 1px; Padding - bottom: 56.25%; Margin-bottom: -1px; margin-bottom: -1px; z-index: -1; } </styleCopy the code

With the CSS custom properties in place, you can use the calc() function to scale the container in proportion:

.container { --ratio: 16/9; height: calc(var(--width) * 1 / (var(--ratio))); width: 100%; } copy codeCopy the code

While simpler than hacks like padding-top, it’s still much more complicated than the native aspect-ratio. That is:

.container { width: 100%; aspect-ratio: 16 / 9; } copy codeCopy the code

Here is an example of how these three different scenarios can achieve the aspect ratio:

Demo: codepen. IO/airen/full /…

You can also use @media to scale elements at different scales on different terminals:

.transition-it { aspect-ratio: 1/1; transition: aspect-ratio .5s ease; @media (orientation: landscape) { & { aspect-ratio: 16/9; }}} Copy the codeCopy the code

CSS Scroll Capture

In Web layouts, it is common to encounter situations where the content container overflows. If overflow is set to Auto or Scroll, the container will display horizontal or vertical scroll bars:

In order to provide users with a better scrolling experience, CSS provides some CSS features to optimize the scrolling experience, and scroll capture is one of them. CSS scroll capture is somewhat similar to Flexbox and Grid layout features. Categories can be used to scroll container properties and scroll item properties:

With the scroll capture feature, we can achieve something like this without relying on any JavaScript libraries or scripts:

Each time you scroll, the center of the image is aligned with the center of the container (think Swiper). The key code is the following lines:

.container { scroll-behavior: smooth; overflow-x: auto; -webkit-overflow-scrolling: touch; scroll-snap-type: x mandatory; scroll-padding: 20px; } img { scroll-snap-align: center; scroll-snap-stop: always; } copy codeCopy the code

Demo: codepen. IO/airen/full /…

Using this feature, you can also achieve some native interactions similar to iOS:

Demo: codepen. IO/airen/full /…

With a little JavaScript scripting, you can also achieve immersive storytelling interaction:

Demo: codepen. IO/airen/full /…

CSS Gap

The appearance of the CSS gap property helps us to solve the layout effect that has been troublesome before:

As shown in the figure above, one desired effect is that there is no spacing right next to the container edges, but there is some spacing (horizontal or vertical) between the adjacent items. Using margin before the gap attribute is annoying, especially if you have multiple rows and columns. Gap requires only one line of code.

The GAP property of CSS is a shorthand property, divided into row-gap and column-gap:

The gap property so far only applies to containers with multi-column layouts, Flexbox layouts, and grid layouts:

// Multi__column {gap: 5ch} // Flexbox layout. Flexbox {display: flex; Gap: 20px} // Grid layout. Grid {display: Grid; Gap: 10vh 20%} Copy codeCopy the code

The GAP attribute can be one or two values:

.gap { gap: 10px; } // equivalent to.gap {row-gap: 10px; column-gap: 10px } .gap { gap: 20px 30px; } // equivalent to.gap {row-gap: 20px; column-gap: 30px; } copy codeCopy the code

If gap has only one value, row-gap and column-gap are the same.

CSS Logical Properties

Most Web developers in China are faced with a relatively simple scenario, which refers to the writing mode or the typesetting mode of reading. Usually LTR (Left To Right). But those who have developed international businesses, such as those in Arab countries, will encounter RTL (Right To Left) scenarios. For example, if you go to Facebook and see the UI in Both Chinese and Arabic:

< HTML > or will be set to the dir attribute (LTR in Chinese and RTL in Arabic) before the logical attribute is seen, and then use different CSS styles for different scenarios:

In fact, in addition to the horizontal (LTR or TRL) way of reading, there will be a vertical way of reading:

In order for Web developers to better provide different typography effects for different reading modes, logical properties have been added to CSS. With logical properties, many of the previous concepts have changed. For example, the familiar axes, x and Y, are now inline and block, and these two axes also change with the writing mode:

In addition, we are familiar with the CSS box model is also divided into physical box model and logical box model:

As you may have noticed, any physical property that previously had the direction top, right, bottom, and left now has inline-start, inline-end, block-start, and block-end logical properties:

According to the W3C specification, I have made a more detailed table of the mapping relationship between physical attributes and logical attributes:

Back to actual production:

To achieve an effect like the one shown above without using logical properties, we need to write CSS like this:

.avatar { margin-right: 1rem; } html[dir="rtl"] .avatar { margin-right: 0; margin-left: 1rem; } copy codeCopy the code

With the CSS logical properties in place, a single line of CSS code can be implemented:

.avatar { margin-inline-end: 1rem; } copy codeCopy the code

Much easier, especially for developers with international needs, is a boon.

CSS Media Query

CSS media query @media is also called CSS query by conditions. Some new media query features are available in Level 5 to query the user’s preferences on the device:

Such as:

  • prefers-reduced-motion
  • prefers-contrast
  • prefers-reduced-transparency
  • prefers-color-scheme
  • inverted-colors

The way it is used is similar to the @media we are familiar with. For example, the Games-color-scheme enables a dark search skin switch:

/ / code from: HTTP: / / https://codepen.io/airen/full/ProgLL / / dark & light mode: root {/ * * / light theme - c - text: # 333; --c-background: #fff; } body { color: var(--c-text); background-color: var(--c-background); } @media (prefers-color-scheme: dark) { :root { /* Dark theme */ --c-text: #fff; --c-background: #333; }} Copy the codeCopy the code

You can also control resource loading based on grid data Settings:

@media (prefers-reduced-data: reduce) { header { background-image: url(/grunge.avif); } } @media (prefers-reduced-data: no-preference) { @font-face { font-family: 'Radness'; src: url(megafile.woff2); }} Copy the codeCopy the code

The use of other methods and effects are not a demonstration. In the future, however, @media for CSS will be easier to write:

@media (width <= 320px) { body { padding-block: var(--sm-space); } } @custom-media --motionOK (prefers-reduced-motion: no-preference); @media (--motionOK) { .card { transition: transform .2s ease; } } .card { @media (--motionOK) { & { transition: transform .2s ease; }} } @media (1024px >= width >= 320px) { body { padding-block: 1rem; }} Copy the codeCopy the code

For the record, this sample code is from @Argyleink’s POWERPOINT.

Since the advent of foldable devices, new challenges have arisen for Web developers:

Thankfully, the teams at Microsoft and Samsung offer different media queries for foldable devices.

Above is a dual screen device with a physical divider:

main { display: grid; gap: env(fold-width); grid-template-columns: env(fold-left) 1fr; } @media (spanning: single-fold-vertical) { aside { flex: 1 1 env(fold-left); }} Copy the codeCopy the code

Seamless folding device:

@media (screen-fold-posture: laptop){ body { display: flex; flex-flow: column nowrap; } .videocall-area, .videocall-controls { flex: 1 1 env(fold-bottom); }} Copy the codeCopy the code

CSS Comparison functions

The CSS comparison functions are min(), Max (), and clamp(). We can pass values or expressions to these functions and they will compare the values and return the most appropriate value. In addition, these are similar to the familiar calc(), which can also help you do dynamic calculations in CSS.

The min () and Max ()

Looking first at min() and Max (), the only difference between them is the return value:

  • min()The function returns a minimum value from multiple arguments (or expressions) as the value of a CSS propertymin()Set the maximum value, which is equal tomax-width
  • max()The function returns a maximum value from multiple arguments (or expressions) as the value of the CSS propertymax()Set minimum value, equivalent tomin-width

The following figure shows how min(50vw, 500px) changes when the browser window width changes:

Demo: codepen. IO/airen/full /…

Replace min() with Max () in the above example, which returns Max (50vw, 500px) :

Demo: codepen. IO/airen/full /…

clamp()

Clamp () is slightly different from min() and Max () in that it returns an interval value, that is, an intermediate value in the range of values defined between the minimum and maximum values. This function takes three arguments:

  • The minimum value (MIN)
  • The median (VAL), also called the preferred value
  • The maximum value (MAX)

Clamp (MIN, VAL, MAX), the relationship between these three values (or how to value them) :

  • ifVALMINMAX, is usedVALAs the return value of the function
  • ifVALIs greater thanMAX, use theMAXAs the return value of the function
  • ifVALLess thanMIN, use theMINAs the return value of the function

For example, here’s an example:

.element {/** * MIN = 100px * VAL = 50vw ➜ MAX = 500px **/ width: clamp(100px, 50vw, 500px); } copy codeCopy the code

For this example, the clamp() function’s calculation goes through the following steps:

.element { width: clamp(100px, 50vw, 500px); /* 50vw is half the viewport width, if the viewport width is 760px, then 50VW is equal to 380px*/ width: clamp(100px, 380px, 500px); */ width: Max (100px, min(380px, 500px)) /*min(380px, 500px) returns 380px*/ width: Max (100px, 380px) /* Max (100px, 380px) returns 380px*/ width: 380px; } copy codeCopy the code

Example effects are as follows:

Demo: codepen. IO/airen/full /…

Simply put, the clamp(), min(), and Max () functions can all adjust the value as the browser window width scales, but their calculated value depends on the context.

Let’s look at a typical case of clamp() in a comparison function. Suppose we need to use different font sizes on different screens (or terminal scenes) :

Before CSS comparison functions existed, a concept called CSS Locks was used to achieve a similar effect:

Some math needs to be done:

Demo: codepen. IO/airen/full /…

Using clamp(), it takes only one line of code to implement:

/** minf: 20px (min font-size) * maxf: 40px (max font-size) * current vw: 100vw * minw: 320px (min viewport's width) * maxw: 960px (max viewport's width) */ h1 { font-size: clamp(20px, 1rem + 3vw, 40px); } copy codeCopy the code

Using this technique, we can easily achieve something like this:

Note: Using CSS Clamp to Create a More Flexible Wrapper Utility.

Visibility of CSS content

Contents-visibilit and Containment -intrinsic-size are included in the CSS Containment Module Level 2. The main function can be used to improve the page rendering performance.

In general, most Web applications have complex UI elements, and some of the content is outside the viewable area of the device (outside the viewable area of the user’s browser). For example, the red area in the following image is outside the viewable area of the mobile device screen:

In this case, we can use the CSS content-visibility to skip the off-screen rendering of the content. That said, if you have a lot of off-screen Content, this will significantly reduce page rendering time.

The Google Chrome team has an engineer who tested Content-visibility:

Using the ‘content-visibility’ property of the CSS makes the browser rendering process much easier. Essentially, this property changes the visibility of an element and manages its render state.

The contain-intrinsic-size attribute controls the natural size of the element specified by content-visibility. Content-visibility treats the height of the element assigned to it as 0, and the browser will change the height of this element to 0 before rendering, thus confusing our page height and scrolling. However, this behavior is overridden if the height has been explicitly set for the element or its children. If you do not have an explicit height set for your element, and do not do so because of the possible side effects of doing so, you can use the contain-intrinsic-size function to ensure that the element is rendered correctly while retaining the benefits of delayed rendering.

In other words, the bonds-intrinsic-size and the content-visibility are generally present together:

section { content-visibility: auto; contain-intrinsic-size: 1000px; } copy codeCopy the code

CSS internal size

If you use the browser Developer tools to review code and hover over a tag, you’ll see something like this:

Intrinsic: intrinsic (800 x 533 px) intrinsic: intrinsic (800 x 533 px) intrinsic: intrinsic (intrinsic: 800 x 533 px) intrinsic

  • External size:252 x 158 px, the developer gaveimgSet dimensions
  • Internal size:800 x 533 px, the original size of the picture

In fact, in CSS to set the size of an element box, some are determined by the content of the element box, some are determined by the context. According to this feature, CSS sizes are also divided into internal (internal) sizes and external (external) sizes.

  • Internal size: When an element is sized according to its own content (including its descendants), regardless of its context; And one ofmin-contentmax-contentfit-contentElement sizes can be determined based on element contents, so they are collectively referred to as internal dimensions.
  • External size: This is when an element does not consider its own content, but rather determines its size based on its context. The most typical example iswidthmin-widthmax-widthAnd so on%The unit value.

Here is a simple example to demonstrate the intrinsic size features of CSS: min-content, max-content, and fit-content.

<h1>CSS is Awesome</h1> <style> h1 { width: auto; } </styleCopy the code

H1 width = auto; min-content = min-content;

H1 {width: auto; } h1 {width: min-content;} h1 {width: min-content; // Copy the code according to the content change}Copy the code

Demo: codepen. IO/airen/full /…

As you can see from the figure above, when width is min-content, h1 is always the length of the word “Awesome” (about 144.52px). Its width has nothing to do with container width changes, but it is influenced by the properties associated with the layout, such as font-size, font-family, and so on.

Let’s look at max-content again:

Demo: codepen. IO/airen/full /…

When h1’s width is max-content, its width is the width of all the content in the line h1 is in. Finally fit-content:

Demo: codepen. IO/airen/full /…

Relatively speaking, fit-content is more complex than min-content and max-content:

h1 { width: fit-content; } // equal to h1 {width: auto; min-width: min-content; max-width: max-content; } copy codeCopy the code

Simply put, fit-content is equivalent to min-content and max-content. It has the following values:

  • If the element has enough Available space,fit-contentWill make usemax-content
  • If the Available space of the element is not sufficient, thanmax-contentSmall, that is to use the value of free space, will not cause content overflow
  • If the Available space of the element is small, thanmin-contentIf you’re young, use itmin-content

Use the following figure to describe the relationship between them:

Min-content, max-content, and fit-content are called internal dimensions and can be applied to properties that set the container size, such as width, height, inline-size, and block-size. But some properties are invalid if used:

  • min-content,max-contentfit-contentUsed forflex-basisinvalid
  • fit-contentInvalid on property used to set grid track size
  • Explicit Settings on a grid project or Flex projectwidth:fit-contentAlso invalid, because their default width ismin-content
  • It’s best not tomin-widthmax-widthFor use onfit-content, easy to cause confusion, suggestions inwidthFor use onfit-content

Using min-content, max-content, or fit-content on the layout can help us design internal layouts, and it’s also very flexible in building some adaptive layouts. Especially when combined with CSS’s Grid and Shapes features, you can build some creative layouts.

Finally, fit-content and fit-content() are not the same thing and should be treated differently.

The display of CSS

Display is not unfamiliar to you, it’s used to format the context, but I’m going to mention it here because there are some changes to display. One of them is that display will in the future support multiple values:

According to the latest information, the Sarafi browser has set display to two values as an experimental property. The meanings of the two values of display are as follows:

Separately, display has added the contennts attribute value, which is described in the W3C specification as follows:

It basically says:

An element with display: contents set will not produce any boxes by itself, but its children will display properly.

Such as:

<div class="outer"> I'm, some content <div class="inner">I'm some inner content </div> </div> <style> .outer { border: 2px solid lightcoral; background-color: lightpink; padding: 20px; } .innter { background-color: #ffdb3a; padding: 20px; } </styleCopy the code

With the simple example code above, you will see something like this:

If we explicitly set display: contents on the.outer element, the element itself will not be rendered, but the children will render normally:

Demo: codepen. IO/airen/full /…

You can use this feature in certain layouts, especially when you don’t want to adjust the structure of your HTML. For example, in Flexbox or Grid, if you want to turn other descendant elements into Grid projects or Flex projects, you can do this:

Demo: codepen. IO/airen/full /…

Display: Contents was very intense during the spec discussion and the display: Subgrid discussion, and display: Contents won. You don’t have a separate display: subgrid in the Grid layout. Instead, move the subgrid to grid-template-columns and grid-template-rows.

Another big fight is over display: contents and Web accessibility. There’s a discussion about this, and if you’re interested, you can read:

  • More accessible markup with display: contents
  • Display: Contents Is Not a CSS Reset

The CSS rules @

There are many types of @ rules in CSS, but the familiar ones are @import, @media, and @supports. Today I will briefly mention a few unusual ones, such as:

  • For nesting@nest@apply
  • Used to register custom properties@property
  • Container queries have been much discussed recently@container
  • @argyleinkMentioned in the newly shared PPT@scope@layer

CSS nested

Those of you who have used CSS processors have used nesting to organize your code, such as SCSS:

// SCSS foo { color: red; & bar { color: green; }} Copy the codeCopy the code

After the above code is compiled:

// CSS foo { color: red; } foo bar { color: green; } copy codeCopy the code

Fortunately, the W3C is also discussing and defining nested rules in CSS. There are two rules:

foo { color: red; @nest bar { color: green; } // or foo {color: red; & bar { color: green; }} foo {color: red; } foo bar { color: green; } copy codeCopy the code

It can also be nested with media query @media:

article { color: darkgray; & > a { color: var(--link-color); } } code > pre { @media (hover) { &:hover { color: hotpink; } } } code > pre { @media (hover) { @nest &:hover { color: hotpink; } } } article { @nest section:focus-within > & { color: hotpink; } } main { padding: var(--space-sm); @media (width >= 540px) { & { padding: var(--space-lg); }}} Copy the codeCopy the code

In addition to @nest, there’s @apply. You may have seen @apply in some front-end frameworks or builders:

If you are in Chrome Canary “Experimental Properties” you can experience @apply directly:

In a nutshell, it is somewhat similar to the hybrid macros @mixin and @extend in SCSS:

:root { --brand-color: red; --heading-style: { color: var(--brand-color); font-family: cursive; font-weight: 700; } } h1 { --brand-color: green; @apply --heading-style; } copy codeCopy the code

CSS Houdini variable at sign property

@property is used to register a variable. This variable is a CSS Houdini variable, but it is used in the same way as a CSS custom property (CSS variable). The difference is that it is registered in the same way:

RegisterProperty ({'name': '--custom-property-name', 'syntax': '<color>', 'initialValue': 'black', 'inherits': False}) // Chrome 85+ // register @property --custom property-name {'syntax': '<color>', 'initialValue': 'black', 'inherits': false} copy codeCopy the code

One of its major features is that you can specify the type, initial value, and inheritance of registered CSS variables:

The photo above was taken from Maxi’s tweet.

Although it is used in a similar way to CSS’s custom properties, it is much more powerful, especially in the area of motion, which can enhance CSS’s motion capabilities and even achieve some of the actions that were previously unavailable to CSS. Such as

@property --hue { initial-value: 0; inherits: false; syntax: '<number>'; } @keyframes rainbow { to { --hue: 360; }} @property --milliseconds {syntax: '<integer>'; initial-value: 0; inherits: false; } .counter { counter-reset: ms var(--milliseconds); animation: count 1s steps(100) infinite; } @keyframes count { to { --milliseconds: 100; }} Copy the codeCopy the code

Combine it with CSS Houdini’s Paint API to do even more:

More on this direction can be found on the Houdini.How website:

Container query @container

Una Kravets shared the container query @Container at Google I/O and called it one of the required features for the new loud layout:

So what can a container query @container do? Let’s say your designer provides you with a design that looks like this:

The first thing you might think of is @media (which seemed to be the only way to do it before there was no container query), but with @Container, you can switch positions:

These two images are from @Shadeed9’s article “CSS Container Queries For Designers”. His other article, “Say Hello To CSS Container Queries,” is also about Container Queries.

It looks very powerful, it is very powerful, and its use is very similar to @Meida:

// Demo: https://codepen.io/una/pen/mdOgyVL .product { contain: layout inline-size; } @container (min-width: 350px) {.card-container {padding: 0.5rem 0 0; display: flex; } .card-container button { /* ... */}} Copy the codeCopy the code

Demo: codepen. IO/una/pen/mdO…

There are some pros and cons to the @Container feature, such as Kenton de Jong in his new post Why I Am Not a Fan of CSS Container Queries that he doesn’t like the T feature:

Personally, I love this feature and will spend some time learning more about @Container. Of course, it’s a good thing to have a discussion, it makes the feature more mature, and if you want to get involved in the discussion, you can join in here.

@ layer and @ the scope

I’ve only seen the @Scope rule before, which is mostly used to deal with the scope of style rules in CSS, but I haven’t really looked into it. Una Kravets saw @Scope again at the Google I/O development Conference share:

The picture above was drawn by Miriam Suzanne!

Styles within @Scope allow for penetration and component-specific styles to avoid naming conflicts, and many frameworks and plug-ins (such as CSS modules) already enable us to do this within frameworks. Now, this specification will allow us to write readable native encapsulation styles of CSS for our components without adjusting tags.

/* @scope (<root>#) [to (<boundary>#)]? {... } */ @scope (.tabs) to (.panel) { :scope { /* targeting the scope root */ } .light-theme :scope .tab { /* contextual Styles */}} Copy the codeCopy the code

Why does it look so similar to Scope in Web Componed?

For @layer, I first see:

@layer reset { * { box-sizing: border-box; } body { margin: 0; }} / /... @layer reset { /* add more later */ } @import url(headings.css) layer(default); @import url(links.css) layer(default); @layer default; @layer theme; @layer components; @import url(theme.css) layer(theme); @layer default, theme, components; @import url(theme.css) layer(theme); @layer framework.theme { p { color: rebeccapurple; } } @layer framework { @layer theme { p { color: cyan; }}} Copy the codeCopy the code

I don’t know what that means, but @Layer is called Cascade Layers. What this feature is ** new to the W3C Cascading and inheritance specification Level5**.

The other…

Not long after I finished and was sorting through this post, I noticed that my idol @Argyleink had shared a similar topic with Hover:CSS! What’s New in 2021? , sharing 31 FEATURES related to CSS, and divided into three levels according to the risk level: high, medium, and low:

You’ll see a lot of similarities with the features I’ve put together. If you’ve heard him share London CSS: What’s New in 2020? At the CSS Conference in London last year, , you’ll find that 2021 is an upgrade from 2020.

After listening to the share in 2020, I also compiled a Chinese version of “2020 YOU should not miss the NEW FEATURES of CSS”, and in the Tao department front end team wechat public account.

To be continued…

It’s a long article, and if you’ve made it this far, you’re a true CSS lover. Thank you for reading, and I will continue to serve you in the future. Share the latest and most interesting aspects of CSS with you!