Pitfalls of custom CSS properties

    Stas Melnikov, the author of the course on Netology “HTML-layout”, told about nuances that can complicate working with custom CSS properties.

    User property name syntax rules


    We are used to the fact that inline CSS properties are case insensitive. Therefore, the following ways to declare properties border will give the same result:

    button {
      BORDER: 2px solid #800080;
    }
    button {
      border: 2px solid #800080;
    }

    User properties, on the other hand, are case-sensitive, so the following example creates two different user properties:

    button {
      --NETOLOGY-BRAND-COLOR: #800080;
      --netology-brand-color: #27ae60;
        
      border: 2px solid var(--NETOLOGY-BRAND-COLOR);
      color: var(--netology-brand-color);  
    }



    Now the frame has become color # 800080 (purple), and the text color is # 27ae60 (green).

    Valid values ​​for custom properties


    With a regular CSS property, you can only set the standard allowed values. According to the custom properties standard, any existing valid CSS value can be used as a value. For example, like all the following custom properties:

    .element::before {
      --color: rgba(0, 0, 0, 1);
      --hex: #000000;
      --value: 20px;
      --number: 3;
      --text: "Hey, what's up?";
      --keyword: currentColor;
    }

    For example, set the frame with color # 800080 for the button:

    button {
      --netologyBrandColor: #800080;
      border-width: 2px;
      border-style: solid;
      border-color: var(--netologyBrandColor);
    }



    In addition to the standard values, you can set one custom property as a value for another.

    button {
      --netologyBrandColor: #800080;
      --buttonBorderColor: var(--netologyBrandColor);
      border-width: 2px;
      border-style: solid;
      border-color: var(--buttonBorderColor);
    }

    The result is nothing different from the previous one, and the button still has a frame with color # 800080.

    If the custom property --netologyBrandColorhas an incorrect value for the property border-color, for example 18px, then the frame will turn black.  

    button {
      --netologyBrandColor: 18px;  
      --buttonBorderColor: var(--netologyBrandColor);
      border-width: 2px;
      border-style: solid;
      border-color: var(--buttonBorderColor);
    }



    The fact is that before the browser applies the value of a custom property to the embedded property, it will check it for correctness. If the value is available for the embedded property, the browser will apply it. And if not, it will set the default value for the embedded property.

    In our case 18px incorrect value for the built-in properties border-color, so the browser will set the default value, ie currentColor. This is very easy to verify by setting the property color to # 800080:

    button {
      --netologyBrandColor: 18px;  
      --buttonBorderColor: var(--netologyBrandColor);
      border-width: 2px;
      border-style: solid;
      border-color: var(--buttonBorderColor);
      color: #800080;
    }



    As you can see, the browser has applied the value # 800080 for the frame. In this example, I used the full syntax to set the frame. But we can use the short one, namely the property border.

    button {
      --netologyBrandColor: 18px;  
      --buttonBorderColor: var(--netologyBrandColor);
      border: 2px solid var(--buttonBorderColor);
      color: #800080;
    }



    Here we have another nuance. The standard has a separate section that describes the behavior of user properties in this situation. According to him, if a user property has an incorrect value for a built-in property, then this user property is not valid, so the browser will ignore the built-in property.

    In our example, the built- border in property has a custom property --buttonBorderColorwith an incorrect value of 18px as one of the values . According to the described algorithm, the browser simply ignored the property border, so the frame element was missing.

    Default value for custom properties


    When we considered an example with a function var, we used only one parameter - the name of a custom property.

    button {
      --netologyBrandColor: #800080;
      border: 2px solid var(--netologyBrandColor);
      color: var(--netologyBrandColor);
    }
    button:hover {
      --netologyBrandColor: #27ae60;
    }

    But besides him, the function var can take the second - the default value. To declare the default value, you need to put a comma after the name of the custom property and write the value itself.


    When the browser realizes that the developer has not declared a value for a custom property, it uses the default value. For example, the value # 800080 (purple) for a custom property --netologyBrandColor.

    button {
      border: 2px solid var(--netologyBrandColor, #800080);
      color: var(--netologyBrandColor, #800080);
    }
    button:hover {
      --netologyBrandColor: #27ae60;
    }
    



    We see that the frame and the text turned purple. But if you hover on the button, they will turn green. This suggests that the browser has applied the value of # 27ae60 to the custom property, thereby replacing the default value.

    But this is not all the features of the function var. In the previous example, the custom property is --netologyBrandColorused twice, respectively, so I set the default value twice.

    But it can be done differently. The function var allows you to pass another function var, so you can set another custom property as the default value. I will rewrite the previous example using a custom property --defaultButtonColor:

    button {
      --defaultButtonColor: #800080;
      
      border: 2px solid var(--netologyBrandColor, var(--defaultButtonColor));
      color: var(--netologyBrandColor, var(--defaultButtonColor));
    }
    button:hover {
      --netologyBrandColor: #27ae60;
    }

    Externally, the result will not change. But now, to change the default value, you need to do it only in one place, and not in several, as before.

    Inheriting custom properties


    CSS has an inheritance mechanism that allows elements to inherit properties on parent elements. In this regard, custom properties are no different from them. For example, I will write code in which the custom property is --netologyBrandColorinherited from the parent element body.

    body {
      --netologyBrandColor: #800080;
    }
    button {
      border: 2px solid var(--netologyBrandColor);
      color: var(--netologyBrandColor);
    }
    </td></tr>



    Looking at the inspector, you can see the inscription "Inherited from body", which shows us that the user property was taken from the element body. But if you button add a custom property for an element --netologyBrandColor, it will already block the property from the element body.

    body {
      --netologyBrandColor: #800080;
    }
    button {
      --netologyBrandColor: #27ae60;
      border: 2px solid var(--netologyBrandColor);
      color: var(--netologyBrandColor);
    }



    In the inspector you can see that the user-defined property of --netologyBrandColorthe element has button redefined the property --netologyBrandColorwe specified for the element body.

    Global values


    The CSS Custom Properties standard introduced a special pseudo-class root, which allows you to specify custom properties that apply to the root element of the document. For example, in an HTML document for an element html.

    :root {
      --netologyBrandColor: #800080;
    }
    button {
      border: 2px solid var(--netologyBrandColor);
      color: var(--netologyBrandColor);
    }



    In the inspector, we can see that the declared custom property applies to the html element. But besides the HTML document, the pseudo-class root  works in SVG documents. For example, I will declare custom properties in the tag style.

    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 28" width="50" height="50">
        <style>
            :root{
                --iconColor: #ffcc00;
                --iconStroke: #000000;
                --iconStrokeWidth: 2px;
            }
        </style>
        <path stroke="var(--iconStroke)" 
              stroke-width="var(--iconStrokeWidth)" 
              fill="var(--iconColor)" 
              d="M26 10.109c0 .281-.203.547-.406.75l-5.672 5.531 1.344 7.812c.016.109.016.203.016.313 0 .406-.187.781-.641.781a1.27 1.27 0 0 1-.625-.187L13 21.422l-7.016 3.687c-.203.109-.406.187-.625.187-.453 0-.656-.375-.656-.781 0-.109.016-.203.031-.313l1.344-7.812L.39 10.859c-.187-.203-.391-.469-.391-.75 0-.469.484-.656.875-.719l7.844-1.141 3.516-7.109c.141-.297.406-.641.766-.641s.625.344.766.641l3.516 7.109 7.844 1.141c.375.063.875.25.875.719z"/>
    </svg>



    And here we see that a pseudo-class has been added to the root element of the SVG root. Accordingly, this proves that the pseudo-class root applies not only to the tag html, but to any root element.

    Conclusion


    In this article, we met with the pitfalls of custom properties that can be confusing. And accordingly, we can begin to use them. Therefore, in the next article I will tell you about the practical tricks that I use in my projects.

    From the Editor


    Courses "Netology" on the topic:


    Also popular now: