Skip to content

Sass - CSS Extensions

Sass extends standard CSS syntax with several features that make writing styles more intuitive, organized, and less repetitive. These extensions seamlessly integrate with familiar CSS concepts.

Perhaps the most iconic Sass feature, nesting allows you to write CSS rules inside one another, mirroring the structure of your HTML. This reduces the need to repeat parent selectors.

SCSS Example:

nav {
background-color: #f8f9fa;
padding: 0.5rem 1rem;
ul {
list-style: none;
margin: 0;
padding: 0;
display: flex;
}
li {
margin-right: 1rem;
}
a {
text-decoration: none;
color: #007bff;
&:hover {
color: #0056b3;
}
}
}

Compiled CSS Output:

nav {
background-color: #f8f9fa;
padding: 0.5rem 1rem;
}
nav ul {
list-style: none;
margin: 0;
padding: 0;
display: flex;
}
nav li {
margin-right: 1rem;
}
nav a {
text-decoration: none;
color: #007bff;
}
nav a:hover {
color: #0056b3;
}

Caution: Avoid nesting too deeply (more than 3-4 levels). Over-nesting can lead to overly specific selectors that are hard to override and increase CSS file size.

Inside a nested rule, the ampersand (&) character acts as a placeholder for the entire parent selector chain. It’s essential for:

  • Pseudo-classes and Pseudo-elements: Attaching :hover, :focus, ::before, ::after, etc., to the parent.
  • Modifier Classes (BEM-style): Creating variations like .block__element--modifier.
  • Contextual Styling: Styling the parent itself when a specific child or condition is met within it.

SCSS Example:

.button {
padding: 10px 15px;
border: 1px solid #ccc;
// Pseudo-class
&:hover {
background-color: #eee;
}
// BEM Modifier
&--primary {
background-color: blue;
color: white;
border-color: blue;
}
// Contextual: Style .button when inside .container
.container & {
margin-bottom: 20px;
}
// Suffixing
&-icon {
// Creates .button-icon
margin-right: 5px;
}
}

Sass allows you to group properties that share a common prefix (namespace) like font, background, border, etc. This can improve organization for properties with multiple sub-properties.

SCSS Example:

.element {
font: {
family: 'Arial', sans-serif;
size: 1.2rem;
weight: bold;
style: italic;
}
border: 1px solid #ccc {
left: none;
radius: 5px;
}
// Equivalent to:
// font-family: 'Arial', sans-serif;
// font-size: 1.2rem;
// font-weight: bold;
// font-style: italic;
// border: 1px solid #ccc; /* This overrides the nested border props below */
// border-left: none;
// border-radius: 5px;
}

Note: While available, nested properties are less commonly used than nested rules. Be aware that setting the shorthand property (like font: ... or border: ...) within the nesting might override the nested sub-properties depending on CSS cascading rules. It often provides only minor readability benefits.

Placeholder selectors start with % and behave like classes, but they are not output in the final CSS unless extended using the @extend directive. They are specifically designed to be used as base styles for inheritance, preventing unused utility classes from cluttering the CSS output.

SCSS Example:

// Define a silent placeholder for shared alert styles
%alert-base {
padding: 15px;
margin-bottom: 1rem;
border: 1px solid transparent;
border-radius: 4px;
}
.alert-success {
@extend %alert-base;
color: #155724;
background-color: #d4edda;
border-color: #c3e6cb;
}
.alert-danger {
@extend %alert-base;
color: #721c24;
background-color: #f8d7da;
border-color: #f5c6cb;
}

Compiled CSS Output:

.alert-success, .alert-danger {
padding: 15px;
margin-bottom: 1rem;
border: 1px solid transparent;
border-radius: 4px;
}
.alert-success {
color: #155724;
background-color: #d4edda;
border-color: #c3e6cb;
}
.alert-danger {
color: #721c24;
background-color: #f8d7da;
border-color: #f5c6cb;
}

Using %placeholder with @extend is often considered the best practice for sharing concrete style rules among related components.