CSS: Supercharge your workflow with advanced features
If you haven't already, I invite you to check out my latest article titled "CSS: Websites Saving Grace (Part 4)". The mentioned article delves deep into CSS Grids and demonstrates how popular websites like Netflix, Instagram Web, and Tiktok Web utilize this efficient layout system to streamline their web design processes with ease and precision.
This article focuses on advanced and efficient features of CSS, such as nesting, CSS variables, and selectors.
What are CSS Selectors?
As mentioned earlier in HTML: "Here's The Main Layout", CSS selectors are identifiers used to target specific HTML elements for styling. They come in various forms, including IDs, classes, and HTML tags themselves. This information is not new and is covered in detail in the aforementioned article.
Furthermore, it's important to understand that these identifiers have a specificity attached to them, which can be modified using different techniques. In this article, we explore another approach to pinpointing the specific HTML element that needs to be styled: using nested selectors.
Nested selectors must follow the structure of the HTML layout; otherwise, no styling will be applied. These selectors are constructed to mimic the nested structure of the HTML, conveying the hierarchical relationships between parent, child, and sibling elements.
To help solidify this understanding, let's consider the following HTML structure outlined below.
<body>
<main class="wrapper">
<section class="main">
<h1>I love pizza</h1>
</section>
</main>
</body>
In CSS, the h1 element can be accessed in these two manners:
-- Option 1 --
h1 {
color: red;
}
-- Option 2 --
.main h1 {
color: red;
}
Option 1 is a generative rule for all h1 element tags and is percieved as suboptimal practice as this introduces future specifity problems. Option 2 is slighty more specific however the problem in above line just filters down a hierarchical level.
With these style rules in place, this instructs CSS to reach into the HTML document find any parent with a class of ".main" and a h1 element as it's child. When found, the appropriate style rules specified are enacted upon the element in question.
As mentioned above Option 2 is still not the best practice to handle a scenario like depicted as specifity is still a major issue enclosed within this approach.
The ideal method is the application of a pseudo selector to the parent element to narrow down the selection of h1 tags even further.
What are Pseudo Selectors ?
CSS selectors become powerful when combined with pseudo-selectors and elements.
These instructions are:
I perceive a distinction between two categories of pseudo-selectors: state pseudo-selectors and static pseudo-selectors, based on whether they are executed at runtime or during rendering.
There is also another group called causal selectors, which combine the functionality of both pseudo-selectors by being able to act upon the element during rendering or upon interaction.
It is worth noting that statically rendered pseudo-selectors create a separate pseudo-element, whereas state pseudo-selectors are attached to elements already present in the HTML document.
Pseudo-selectors such as :hover, :focus, and :active represent the state as they are executed upon interactivity of the element at runtime, while pseudo-selectors like :before, :after, and the remaining ones are statically rendered.
Selectors like .main > h1, .main + h1, and .main ~ h1 are all examples of causal selectors.
:hover
It selects an element when the mouse cursor is hovering over it. This is often used to apply hover effects. An example of use can be shown in this small video
:focus
Another of the state pseudo-selectors, useful to attach a certain style rule to elements when interacted upon and in focus "state". Focus state indicates the element has been clicked upon and mouse is no longer present among the element's boundaries.
:active
The last of the state pseudo-selectors which is attached to the element to style the particular element when the element is "active" on the page.
The distinction between the :focus pseudo-selector and the :active pseudo-selector is evident during interaction with the element.
The :focus state is triggered when the element is clicked and subsequently left alone. On the other hand, the :active state is activated when the mouse is continuously held down on the element.
:before
First of the statically rendered pseudo-elements. Enables addition of elements before the target element specified. By default, in CSS, when you use the :before or :after (explained below) pseudo-selector to add content before the target element, the rendered pseudo-element is given a default positioning of position: static.
With position: static, the pseudo-element is not affected by the positioning properties such as top, bottom, left, or right. It is rendered in the normal flow of the document, just like any other inline or block element. It appears before the content of the target element in the document flow, but it does not create a new stacking context or affect the positioning of other elements.
Another point of note is the element created does not hold any content and is thus a width and height of 0. The elements height and weight value would need to be specified explicitly (values stated) or implicitly (via content dimensions).
Here's another short snippet video of the use of :before
:after
This pseudo-selector is self-describing, especially when the above :before pseudo selector description is taken into context. Evidently, the :after performs the same functionality as the :before selector, however the rendered pseudo element is placed after the element the pseudo-selector is used upon.
-- index.html --
<body>
<main class="wrapper">
<header></header>
<section class="main">
<button class="btn">Hello</button>
</section>
<footer></footer>
</main>
</body>
-- main.css --
html, body {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.wrapper{
min-height: 100vh;
}
header, footer {
width: 100vw;
height: 10vh;
}
header {
background: orange;
}
.main{
height: 80vh;
display: grid;
place-items: center;
}
/* .btn:before{
content: '\1F44B \0020\0020';
} */
.btn {
border: none;
outline: none;
--webkit-appearance: none;
--moz-appearance: none;
appearance: none;
padding: .5em 2em;
border-radius: 5px;
text-transform: uppercase;
display: inline-block;
}
.btn:after{
height: 20vh;
width: 5vw;
background: red;
content: '';
display: inline-block;
}
footer {
background: red;
}
Recommended by LinkedIn
Causal Selectors
Causal selectors in CSS are a group of selectors that allow you to target elements based on their relationship to other elements within the same parent container. These selectors provide a way to style specific elements that have a cause-and-effect relationship with other elements. Causal selectors include .main > h1, which targets an h1 element that is a direct child of an element with the class "main". Additionally, .main + h1 targets an h1 element that immediately follows an element with the class "main". Lastly, .main ~ h1 selects an h1 element that follows an element with the class "main" within the same parent container. By using these causal selectors, you can apply unique styles to specific elements based on their positional relationship to other elements, enhancing the presentation and visual hierarchy of your web page.
-- index.html --
<div class="main">
<h1>This is a heading inside the main div</h1>
</div>
-- main.css --
.main > h1 {
color: red;
}
The selector .main > h1 targets an h1 element that is a direct child of an element with the class "main". In the provided example, the selector would apply to the <h1> element within the <div> element with the class "main".
2. .main + h1:
-- index.html --
<body>
<main class="wrapper">
<header></header>
<h2 class="main">Yo</section>
<h1>This is a heading inside the main div</h1>
<footer></footer>
</main>
</body>
-- main.css --
html, body{
margin: 0;
padding: 0;
box-sizing: border-box;
}
.wrapper{
min-height: 100vh;
}
header, footer {
width: 100vw;
height: 10vh;
}
header {
background: orange;
}
.main + h1{
color: red;
}
footer {
background: red;
}
The selector .main + h1 targets an h1 element that immediately follows an element with the class "main". In the provided example, the selector would apply to the <h1> element that comes right after the <div> element with the class "main".
3. .main ~ h1:
-- index.html --
<div class="main"></div>
<p>This is a paragraph adjacent to the main div</p>
<h1>This is a heading adjacent to the main div</h1>
-- main.css --
html,
body {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.wrapper{
min-height: 100vh;
}
header, footer {
width: 100vw;
height: 10vh;
}
header {
background: orange;
}
.main ~ h1 {
color: red;
}
footer {
background: red;
}
The selector .main ~ h1 targets an h1 element that follows an element with the class "main" within the same parent container. In the provided example, the selector would apply to the <h1> element that comes after the <div> element with the class "main".
CSS Variables ?
CSS variables are like containers that hold different values, just like a box can hold tools or books. These variables allow us to store and reuse values throughout our CSS code. We can give these variables names, so it's easier to remember and use them.
Imagine you're designing a website, and you want to use the same color in multiple places, like the background color and the text color. Instead of writing the color value every time you need it, you can create a CSS variable and assign the color value to it. Let's call it --primary-color.
:root {
--primary-color: blue;
}
h1 {
color: var(--primary-color);
}
p {
background-color: var(--primary-color);
}
In the example above, we set the value of --primary-color to blue inside the :root selector. The :root selector is a special selector that represents the root element of the document, which is usually the <html> tag. By defining the variable at the root level, it becomes available for use in any part of the CSS code.
Now, when we apply the --primary-color variable to the color property of the h1 selector and the background-color property of the p selector, they will both take on the value of blue. So, if we decide to change the primary color to, let's say, green, we only need to update the value of --primary-color in one place (inside :root), and the change will be reflected everywhere the variable is used.
CSS variables make it easier to manage and update values throughout a website, providing a way to maintain consistency and make changes more efficiently. Just like using boxes to store and organize different things, CSS variables help keep our code neat and reusable, making it easier to create and maintain beautiful websites.
Nesting in CSS ?
In native CSS, nesting refers to the concept of placing selectors and their associated styles within the scope of another selector.
It allows you to target specific elements within the context of their parent elements, making your CSS more concise and organized.
To enable nesting in CSS, a preprocessor language such as SASS or SCSS is commonly used. These languages provide additional features and shorter syntax for writing style rules. When using SASS as your preferred CSS preprocessor, the code written in the SASS language needs to be compiled.
In simple terms, compilation means taking the input file written with the special syntax of the chosen language (like SASS) and transforming it back into its original form: CSS. The compilation process allows the browser to understand and render the CSS code correctly.
To take an example of this in action, the following code is necessary:
-- index.html --
<body>
<main class="wrapper">
<header></header>
<div class="main">
<p>This is a paragraph adjacent to the main div</p>
<h1>This is a heading adjacent to the main div</h1>
</div>
<footer></footer>
</main>
</body>
Styling any elements inside of the .main container element would involve creating separate style rules:
-- main.css --
.main h1 {
color: blue;
}
.main p {
color: red;
}
However, with the power of CSS nesting, we can reduce the amount of code necessary and remove code duplication.
-- main.css --
.main {
h1{
color: blue;
}
p{
color: red;
}
}
The code above is not suitable and wouldn't be able to be adopted and usable on a website as is, this code needs to be compiled at buildtime. So, the following process takes place under the hood:
Note: Normally, a build and management tool like Gulp is used to streamline this process to execute on file save or build command automatically. Gulp will be covered in its entirety along with Webpack in following videos.
SASS offers built-in functionalities that resemble those of a programming language, making it highly versatile and powerful for CSS preprocessing.
SASS and SCSS (which is a superset of SASS) provide additional capabilities beyond what regular CSS offers. These functionalities include variables, mixins, functions, loops, and conditionals. Let's only take a snapshot look at some of these features as these are inherently programming language features which will be covered in following articles.
With these advanced features, SASS/SCSS enhances the development experience by making CSS more modular, reusable, and maintainable. It brings the power of a programming-like approach to CSS, enabling developers to write more efficient and flexible stylesheets. The SASS/SCSS code is then compiled into regular CSS, which the browser can understand and render correctly.