In the previous chapter, we saw the challenges of building a webpage using raw CSS, evident from the 340 lines of code required for a basic YouTube homepage. The complexity of modern web design necessitates more efficient solutions, and this is why various CSS tools and frameworks are created. These resources are designed to enhance code quality and accelerate the development process. In this chapter, we will delve into some popular tools and frameworks and briefly discuss how to use them to optimize your development workflow.
📧 Subscribe to my newsletter: https://ericsdevblog.ck.page/profile
CSS preprocessor
A CSS preprocessor is a program that can generate CSS code from unique scripting languages. The scripting language possesses programming features such as variables, nesting, functions, and so on, hence extending the capabilities of raw CSS.
The most popular CSS preprocessors include Sass and Less. Sass stands for Syntactically Awesome Stylesheets, which is written in Ruby, a popular programming language known for its simplicity and productivity. On the other hand, Less is short for Leaner Style Sheets, a preprocessor written in JavaScript, one of the most popular programming languages, making it compatible with various web development environments.
Both tools offer similar features to improve your development process, and for demonstration purposes, I will use Less as an example because it is the more popular option. At the time this course is finished, Less has 17k stars on GitHub, compared to Sass, which has 14.7k stars.
Less can be installed into your project using npm, a package manager for JavaScript. We will talk more about this in the JavaScript course in the feature. For now, you only need to know that Less can be installed with the following command:
npm install less -g
And to compile a .less
file into .css
, use this command:
lessc input.less style.css
In this case, input.less
file will be compiled into style.css
.
Less adds programming features to your CSS code, such as user-defined variables, custom functions, mixins, imports, inheritance, and more. Let's take a look at some examples:
- Creation of variables
Less allows you to define variables that can be accessed anywhere in the .less
file.
@primary-color: #3498db;
.button {
background-color: @primary-color;
}
.heading {
color: @primary-color;
}
The compiled CSS file looks like this:
.button {
background-color: #3498db;
}
.heading {
color: #3498db;
}
Recall that it is possible to create variables using raw CSS as well.
:root {
--primary-color: salmon;
}
p {
color: var(--primary-color);
}
However, as you can see, you need to retrieve the variable using the var()
function. Using a preprocessor makes this process much simpler.
- Nesting of selectors
Less also allows for the nesting of selectors, providing a more structured and readable way to write styles.
nav {
ul {
margin: 0;
padding: 0;
list-style: none;
}
li {
display: inline;
}
a {
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
}
The generated CSS:
nav ul {
margin: 0;
padding: 0;
list-style: none;
}
nav li {
display: inline;
}
nav a {
text-decoration: none;
}
nav a:hover {
text-decoration: underline;
}
- Import other Sass/Less files
You can also create partial Less files that can be imported into other Less files. This feature promotes modularization and reusability, making it easier for you to manage the project structure.
_variables.less
@base-font-size: 16px;
@heading-font-size: 24px;
@spacing-unit: 10px;
styles.less
@import "variables.less";
- Mixins
A mixin is a group of CSS declarations that can be reused in different parts of the file.
.border-radius(@radius) {
border-radius: @radius;
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
}
.button {
width: 100px;
height: 40px;
background-color: blue;
.border-radius(5px);
}
- Inheritance
Inheritance is a feature that allows styles from one selector to be inherited by another selector. For example, you are creating different alert messages, which have the same size, font, and border. The only thing different is the text color. You can create a .message
selector and let all other .*-message
selectors inherit from .message
like this:
.message {
padding: 10px;
border: 1px solid #ccc;
}
.success-message {
&:extend(.message);
background-color: #4caf50;
color: #fff;
}
.error-message {
&:extend(.message);
background-color: #f44336;
color: #fff;
}
The output looks like this:
.message,
.success-message,
.error-message {
padding: 10px;
border: 1px solid #ccc;
}
.success-message {
background-color: #4caf50;
color: #fff;
}
.error-message {
background-color: #f44336;
color: #fff;
}
As you can see, it helps you avoid a lot of unnecessary repetition.
- Custom functions
This is different from the CSS functions we discussed before, as these functions are defined by you. Let's look at this example:
double(@value) {
@result: @value * 2;
return @result;
}
.example {
width: @width;
height: double(10px);
}
The double()
function is not a built-in function. It is created within the context of the specific project. The custom functions provide a powerful mechanism for creating dynamic styles.
Comparing Sass and Less, they are similar in many ways, as they both offer powerful features to improve CSS development. The choice between them often comes down to personal preference, project requirements, and the existing toolset and environment of a development team.
PostCSS
Contrary to the preprocessors, PostCSS is a CSS postprocessor that will parse existing CSS code to enhance its functionality, efficiency, and compatibility.
With the right plugin, you can use PostCSS to automatically add the correct vendor prefix, ensuring compatibility with different browsers. For example, some CSS properties require you to have the -webkit-
prefix to work on Safari, and -ms-
prefix to work on older versions of Microsoft Edge, before Chromium.
Let's say you have this CSS code:
body {
display: flex;
align-items: center;
justify-content: center;
}
To ensure compatibility on all platforms, PostCSS will transform it into:
body {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
}
PostCSS can also minimize your CSS file by removing unnecessary white spaces. The result will be difficult for humans to understand, but it won't be a problem for machines.
.button {
background-color: #3498db;
}
.heading {
color: #3498db;
}
nav ul {
margin: 0;
padding: 0;
list-style: none;
}
nav li {
display: inline;
}
nav a {
text-decoration: none;
}
nav a:hover {
text-decoration: underline;
}
.message,
.success-message,
.error-message {
padding: 10px;
border: 1px solid #ccc;
}
.success-message {
background-color: #4caf50;
color: #fff;
}
.error-message {
background-color: #f44336;
color: #fff;
}
Output:
.button{background-color:#3498db}.heading{color:#3498db}nav ul{margin:0;padding:0;list-style:none}nav li{display:inline}nav a{text-decoration:none}nav a:hover{text-decoration:underline}.message,.success-message,.error-message{padding:10px;border:1px solid #ccc}.success-message{background-color:#4caf50;color:#fff}.error-message{background-color:#f44336;color:#fff}
Besides autoprefixing and minification, PostCSS can also run linters to analyze the code for potential errors, help manage the media queries, inline small images into CSS as data URLs to improve page load times, and so much more. PostCSS can perform a wide range of transformations to enhance the performance, maintainability, and cross-browser compatibility of your CSS files.
Popular CSS frameworks
When we recreated the YouTube homepage together, remember that we started by designing the page layout to see what content needed to be present in the webpage. Then, we moved to the HTML code to ensure all the elements were included, and finally, we wrote the CSS code to make sure the elements were displayed as designed.
The CSS frameworks simplifies this process by removing the final step. A framework is a collection of prebuilt CSS styles with intuitive class names. All you need to do is put the right class name to the right element. Just like when we discussed the legacy layout method. We created the CSS file first:
.col-1 {width: 8.33%;}
.col-2 {width: 16.66%;}
.col-3 {width: 25%;}
.col-4 {width: 33.33%;}
.col-5 {width: 41.66%;}
.col-6 {width: 50%;}
.col-7 {width: 58.33%;}
.col-8 {width: 66.66%;}
.col-9 {width: 75%;}
.col-10 {width: 83.33%;}
.col-11 {width: 91.66%;}
.col-12 {width: 100%;}
@media screen and (min-width: 640px) {
.col-md-1 {width: 8.33%;}
.col-md-2 {width: 16.66%;}
.col-md-3 {width: 25%;}
. . .
}
@media screen and (min-width: 1024px) {
.col-lg-1 {width: 8.33%;}
.col-lg-2 {width: 16.66%;}
.col-lg-3 {width: 25%;}
. . .
}
And then, in order to create a <div>
that takes the full width on small screens, six columns on medium screens, and two columns on large screens, you only need to put the right class names to the <div>
element.
<div class="col-12 col-md-6 col-lg-2">Lorem ipsum dolor sit. . .</div>
CSS frameworks are essentially the same, except they cover much more than creating columns.
Some commonly used frameworks include Bootstrap, TailwindCSS, Bulma, Foundation, and so on. TailwindCSS is my personal favorite, as it is a utility-first CSS framework that provides low-level utility classes for any custom designs. It is highly customizable and configurable. You can customize it to suit your own unique design preferences.
For example, here is a basic login form I created using TailwindCSS without having to write a single line of CSS.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="p-4">
<div class="max-w-md mx-auto bg-white p-6 rounded-md shadow-lg">
<h2 class="text-xl font-bold mb-4">Login</h2>
<form>
<div class="mb-4">
<label
for="username"
class="block text-gray-700 text-sm font-bold mb-2"
>Username</label
>
<input
type="text"
id="username"
name="username"
class="w-full px-3 py-2 border rounded-md"
placeholder="Enter your username" />
</div>
<div class="mb-6">
<label
for="password"
class="block text-gray-700 text-sm font-bold mb-2"
>Password</label
>
<input
type="password"
id="password"
name="password"
class="w-full px-3 py-2 border rounded-md"
placeholder="Enter your password" />
</div>
<button
type="submit"
class="bg-blue-500 text-white py-2 px-4 rounded-md hover:bg-blue-700">
Login
</button>
</form>
</div>
</body>
</html>
Top comments (0)