📜 ⬆️ ⬇️

12 little-known facts about CSS (continued)

More than a year ago I published 12 little-known facts about CSS (Habré translation ), and to this day it was one of the most popular articles on SitePoint. Since then I have collected more interesting and small CSS tips for a new publication. We all know that every successful film should contribute to the release of the newfangled sequel, right?


Author of illustration SitePoint / Natalia Balska .

So let's look at this year’s selection of dozens of obscure facts about CSS. I'm sure many of you know at least some of them, but you can let me know in the comments how many of the facts turned out to be new to you.
')
Translator's Note
0. Yes, I saw a translation of the same article published a couple of hours ago. But my conscience will not allow me to remove the many days of work due to being late for a couple of hours :) in general, in your judgment.

1. The original article is replete with working demonstrations with CodePen. Habr, unfortunately, does not support insertions from similar resources, and I think it makes no sense to replace dynamic working examples with static images. Therefore, the article turned out to be a little “bald” sheet, but, I hope, interested readers will discover the missing examples from the links in a new window.

2. Although I have a direct bearing on the layout, the translation was large and not as simple as it seemed at first. Notes on errors, typos, terminology, etc. please send a personal message to habraposhta.


1. In the property border-radius you can use the "slash" syntax


I already wrote about this on SitePoint more than four years ago, but I think that many beginners and even some experienced developers are not aware of this possibility.

Believe it or not, the following code is valid:

 .box { border-radius: 35px 25px 30px 20px / 35px 25px 15px 30px; } 

If you have never seen this syntax, it may seem a bit confusing, so I’ll provide an explanation from the specification:

If the values ​​are specified before and after the slash, then the values ​​before the slash set the horizontal radius, and the values ​​after the slash - vertical. If no slash is used, the values ​​of both radii (both horizontal and vertical) are considered the same.

The specification also shows the following scheme:



In the explanation to the picture it says: "Two values ​​of the border-top-left-radius: 55pt 25pt determine the curvature of the angle."

Thus, the use of a slash in the values ​​of the border-radius property allows you to create asymmetrically curved corners ( note of the translator: rounds ). If you want to understand this in more detail, read my article (the link to which was cited above), or better see a convenient interactive demonstration from MDN .

Most border-radius generators do not allow the use of these optional values. Of those that I found, the only generator from MDN supports the “slash” syntax.

2. The font-weight property supports relativity keywords


Usually, when you see the description of the font-weight property, the value in it is either normal or bold . You could also see integer values ​​with an increment of a hundred: 100 , 200 , etc. up to 900

However, there are two values ​​that are often forgotten: the bolder and the lighter .

According to the specification, these keywords make the font fatter or thinner relative to the inherited value. The most important thing is that it works when you are dealing with a font that supports several degrees of “boldness”, which supports fonts that are thicker than regular bold and thinner than just normal text.

In syntax based on integer values, 700 means bold and 400 means normal . So, if your font supports a thickness of 300 , but not less, the lighter value will use a thickness of 300 if the inherited font thickness is 400 . If the font does not support a finer type (i.e., the default value of 400 is the thinnest), then the thickness will remain 400 , and the lighter value will have no effect on the text.

Look at the following example .

In this example, I use the Exo 2 font, which supports 18 different styles. My demo does not use italic styles, but the font supports them for each value from 100 to 900 .

The example includes 12 nested “box” elements with different font-weight values, including bolder and lighter , so you can see how this affects the “fatness” of the text in different cases of inheritance. Below the spoiler is the CSS from the example. Pay attention to the comments in the code, and remember that every next “box” element is nested in the previous one:

CSS from example
 .box { font-weight: 100; } .box-2 { font-weight: bolder; /*   400 */ } .box-3 { font-weight: bolder; /*   700 */ } .box-4 { font-weight: 400; } .box-5 { font-weight: bolder; /*   700 */ } .box-6 { font-weight: bolder; /*   900 */ } .box-7 { font-weight: 700; } .box-8 { font-weight: bolder; /*   900 */ } .box-9 { font-weight: bolder; /*   900 */ } .box-10 { font-weight: lighter; /*   700 */ } .box-11 { font-weight: lighter; /*   400 */ } .box-12 { font-weight: lighter; /*   100 */ } 


In this case, the key owl “bolder” and “lighter” set the font-weight to values 100 , 400 , 700 and 900 . With nine different styles, these keywords will never lead to values ​​of 200 , 300 , 500 , 600 and 800 .

This happens because you tell the browser to select the next font in the series that is “fatter” or “thinner”. But the browser chooses not just the next option fatter or thinner, but the option of fatter or fatter relative to the current one. However, if the thinnest font style begins with a value of 300 (as in the Open Sans font ), and the default value is 400 , then using the “lighter” keyword will set the font-weight to a value of 300 .

This may seem confusing, but you can play around with an example to understand how these keywords work.

3. The outline-offset property


The outline property is well known for its convenience when debugging typesetting (the outline of an element does not affect the surrounding elements in any way ). In the specification, however, the outline-offset property has also been added, which does exactly what its name implies - it allows you to set the margin indent from the element.

Example of outline-offset .

In this example, move the slider left / right to see how this affects the contour indent from the element. In this case, the indent varies from 0px to 30px , but in CSS you can specify any indent. It should be remembered that although outline and a universal property (at the same time setting the color, style, and thickness of the outer border), it does not include outline-offset . Therefore, if necessary, the outline-offset each time you need to register separately.

The only negative outline-offset is that it is supported by all browsers except Internet Explorer (it does not even support IE 11).

4. CSS has table-layout property


You will probably say: “Ha, as old as the world. I know about display:table . The simplest way to vertical centering. ” But this is not what I want to talk about. Notice, I said the table-layout property, not the display .

The table-layout property is not the easiest CSS feature to explain how it works. Therefore, let's look at the specification, and then consider an example. The specification reads as follows:

At the same time (fast) algorithm, the horizontal breakdown of the table does not depend on the content in the cells; depends only on the width of the table, the width of the columns and borders or the distance between cells.

This seems to be the first time that something is difficult to understand in the W3C specification ... Hah, just joked ( comment of the translator: in the original “LOL JK” ).

But seriously, as always a living example will help us. In this demo table in CSS added table-layout: fixed . Click the button to turn this feature off / on.

In this example, you can see the advantage of using table-layout: fixed over table-layout: auto . Such an approach will not always be the best choice and is not always necessary, but it would not be bad to know about it when it comes to tables with cells of irregular width.

Last year, Chris Coyier wrote an excellent article on table-layout , so if you want to know more about this property, I advise you to read.

5. The vertical-align property in table cells works differently than in other elements.


If you were creating websites in the mid-2000s and earlier or often HTML-letters for email lists, you probably assume that the vertical-align CSS property is analogous to the old HTML4 attribute valign , which is no longer supported in HTML5 .

But the vertical-align CSS property doesn't work the same way, especially with tables. This, in my opinion, is weird, but still better than if the property did not work in tables at all.

So what is the difference between applying a property to ordinary elements and to table cells?

If vertical-align does not apply to table cells, then follow these simple rules:


In this example, the vertical-align property is assigned to the input element. By clicking on the buttons you can set the property values ​​written on the buttons. Notice how each value changes the position of the input element.

In general, this is a fairly simple demonstration of the property. For more in-depth analysis, read Christopher Aue last year’s article .

When it comes to tables, vertical-align works quite differently. In this case, you apply the property to one or more cells, and the alignment of the content of the cells depends on the selected value. CodePen example .

As shown in the example, only 4 values ​​of the vertical-align property are applicable to table cells. In addition, the baseline value affects not only the cell to which it is affixed, but also the neighboring cells in the row of the table.

6. The pseudo-element ::first-letter smarter than you thought.


The pseudo-element ::first-letter allows you to stylize the first letter of any element and makes it possible to realize the effect of the initial letter ( comment of the translator: I allowed myself to refer to the Russian-language wiki page ), which has been circulated in print for many years.

The good news is that browsers seem to have the same idea about the “first letter” of an element. I first read about this in a tweet by Matt Andrews (Matt Andrews), although he clearly did not like this browser behavior. You can see his example on CodePen .


It seems to me that the big four browsers work with this property in the same way, and this is cool, because I think this is the right behavior. It would be a little strange if the opening bracket was considered the first letter. In this case, it would be similar to the “first character” (first character), which could become an independent pseudo-class.

7. In HTML, you can use invalid characters as a separator in the list of element classes.


This approach was discussed in 2013 by Ben Everard, and I think it’s worth a closer look at this topic.

Ben's publication talked about using a slash ("/") to split class lists in HTML into groups to make the code easier to read and understand. The author points out that although the slash is an invalid character, browsers will not stumble on it, but simply ignore it.

Suppose you have this HTML:

 <div class="col col-4 col-8 c-list bx bx--rounded bx--transparent"> 

With slashes, it will look like this:

 <div class="col col-4 col-8 / c-list / bx bx--rounded bx--transparent"> 


You can use any characters (both valid and invalid) as separators:

 <div class="col col-4 col-8 ** c-list ** bx bx--rounded bx--transparent"> <div class="col col-4 col-8 || c-list || bx bx--rounded bx--transparent"> <div class="col col-4 col-8 && c-list && bx bx--rounded bx--transparent"> 

All such constructions work fine, you can test on this demo .

Of course, these delimiters cannot be used as classes, so I call them "invalid." The following code will be disabled and will not apply styles to the element:

 ./ { color: blue; } 

If you want to use such characters in class names, while maintaining their functionality, you can escape them by using this tool . The previous example will work only if the CSS looks like this:

 .\/ { color: blue; } 

Delving into the details, I will say that Unicode characters do not need to be escaped, so you can use these crazy constructions:

 <div class=" ★"></div> 


With this CSS:

 . { color: hotpink; } .★ { color: yellow; } 

It is also possible to escape characters of this type, instead of directly inserting them. The following code is equivalent to the previous one:

 .\2665 { color: hotpink; } .\2605 { color: yellow; } 

8. The number of repetitions of animation can take fractional values.


You probably know that when using keyframe animations, you can use the animation-iteration-count property to set the number of animation repeats:

 .example { animation-iteration-count: 3; } 

The integer value in this case means that the animation needs to be repeated 3 times. But perhaps you are not aware that fractional values ​​can be set:

 .example { animation-iteration-count: .5; } 

In this case, only half of the animation will start (it will stop at half past the first iteration). Let's look at an example in which two balls are animated. At the top ball, the repeat counter is set to “1”, and at the bottom one to “0.5”.

Interestingly, the repeat count does not depend on the property / value that is being animated. In other words, if you are animating some 100 pixels, this does not mean that the animation will stop at 50 pixels on half of the replay. The previous example uses the timing function linear , which ensures that the second ball stops half way.

Here are two more animations, but here the timing function ease already used: an example . Please note that now the second ball also passed halfway through the animation. I repeat, this happens because of the different timing functions.

If you understand the timing function, you will understand why the ball stops at the same position as at linear with ease-in-out . Play around with different fractional values ​​and timing functions to see how this affects the result.

9. Animation may not work due to the name of the animation.


Some developers have discovered this by chance on their own experience, although there is a warning about this in the specification. Suppose you have the following animation code:

 @keyframes reverse { from { left: 0; } to { left: 300px; } } .example { animation: reverse 2s 1s; } 

Notice, for animation, I use the name reverse . At first glance, the code looks working, but notice what happens if we use it in a live example .

Animation does not work, since “reverse” is a reserved keyword for the animation-direction property. This will happen with any animation whose name matches the reserved keywords used in the universal (short) recording method. With a detailed recording form, with separate indication of the animation-name and other parameters, the animation will work.

The names of the animations that can break the short form of the record include the names of the timing functions , such as infinite , alternate , running , paused , etc.

10. You can select a range of items.


I do not know who first used this opportunity, but I first learned about it from this example from Gunnar Bittersmann. Let's say you have a numbered list of 20 items and you want to select items 7 through 14 inclusive. Here's how to do this with one selector:

 ol li:nth-child(n+7):nth-child(-n+14) { background: lightpink; } 

See the demo of the selector .

Update: As noted in the comments, in Safari there is a bug, because of which this technique does not work. Fortunately, the solution proposed by Matt Pomaski seems to work: just expand the pseudo-class chain to get the ol li:nth-child(-n+14):nth-child(n+7) selector ol li:nth-child(-n+14):nth-child(n+7) . In the nightly builds of WebKit, there is no such bug, so over time, and in Safari, this design will work fine.

This code uses a bunch of pseudo-classes with expressions. Although expressions may seem confusing, you can see the selection of elements in the numbers used in these expressions.

How it works: In the first part of the bundle, the expression says “choose the 7th element and each after it”. The second part says “choose the 14th element and each one before it”. But since the selectors are in a bundle, each restricts the sample area of ​​the other. So the second part of the bundle does not allow the first to get out of the 14th element, and the first part does not allow the second to go down in the sample below the 7th element.

For a more detailed study of these types of selectors and expressions, you can read my old post on this topic .

11. Pseudo-elements can be applied to some single tags.


Perhaps you, like me, at some point tried to apply pseudo-elements to images or form elements. This will not work, because pseudo-elements do not work with replaceable elements. I think many developers assume that this applies to all single tags (not having a closing tag). But it is not.

You can apply pseudo-elements to some single tags that are not replaceable elements. This also applies to the hr element, as can be seen from this example .

The shaded area in this example is the horizontal essay ( hr element), and both the pseudo-elements ::before and ::after applied to it. Interestingly, I was not able to get the same result with br , although it is an indispensable one-tag element.

You can also add pseudo-elements to the meta and link elements if you are abnormal enough to make them display: block , as shown in the following example .

12. Some values ​​in attribute selectors are case-insensitive.


In conclusion, consider one small obscurity. Suppose you have the following HTML:

 <div class="box"></div> <input type="email"> 

You can apply styles to each of these elements using attribute selectors, like this:

 div[class="box"] { color: blue; } input[type="email"] { border: solid 1px red; } 

Such styles work fine. And what if you do this?

 div[class="BOX"] { color: blue; } input[type="EMAIL"] { border: solid 1px red; } 

Notice that the attribute values ​​are now uppercase. In this case, styles will not be applied to the .box element, since the class attribute is case-sensitive. On the other hand, email styles are applied to the field because the values ​​of the type attribute are not case sensitive. There is no discovery here, but perhaps you did not know about it.

People it's time to wrap up


At that moment the curtain goes down, and the hope-not-too-crappy sequel ends.

It is felt that every week I stumble upon some small CSS of interestingness and study them, and I hope that something from the above described has been cognitive for most of you. What are your favorite little known CSS tricks or techniques? Do you know CSS features or features that you consider to be little-known but well supported browsers? Share them in the comments.

Source: https://habr.com/ru/post/262783/


All Articles