Odd CSS syntax. [class^='icon-'], [class*=' icon-']
Categories:
Demystifying CSS Attribute Selectors: [class^='icon-']
and [class*=' icon-']
![Hero image for Odd CSS syntax. [class^='icon-'], [class*=' icon-']](/img/1af295c0-hero.webp)
Explore the powerful and often misunderstood CSS attribute selectors [class^='icon-']
and [class*=' icon-']
. Learn how they target elements based on class names, their use cases, and best practices for effective styling.
CSS attribute selectors provide a flexible way to style elements based on the presence or value of their attributes. Among these, [attribute^=value]
(starts with) and [attribute*=value]
(contains substring) are particularly useful for targeting elements with specific class naming conventions. This article delves into two common patterns: [class^='icon-']
and [class*=' icon-']
, explaining their distinct behaviors and practical applications in modern web development.
Understanding [class^='icon-']
The [attribute^=value]
selector targets elements where the specified attribute's value begins with the given string. When applied to the class
attribute as [class^='icon-']
, it selects any element whose class
attribute value starts with icon-
. This is incredibly useful for styling elements that follow a strict naming convention, such as a set of icons where all icon classes begin with a common prefix.
/* Selects elements with classes like 'icon-home', 'icon-user', 'icon-settings' */
[class^='icon-'] {
display: inline-block;
width: 24px;
height: 24px;
background-size: contain;
background-repeat: no-repeat;
vertical-align: middle;
}
Basic styling for elements whose class attribute starts with 'icon-'
This selector is precise. It will match <i class="icon-home"></i>
but not <i class="my-icon-home"></i>
. It's ideal for scenarios where you control the class naming and want to apply base styles to a group of related components.
Understanding [class*=' icon-']
The [attribute*=value]
selector targets elements where the specified attribute's value contains the given string as a substring. When used as [class*=' icon-']
, it selects elements whose class
attribute value contains the substring icon-
. Notice the leading space in icon-
. This space is crucial because it ensures that the selector matches a full class name, not just a part of a longer class name.
/* Selects elements with classes like 'btn icon-add', 'item icon-delete', 'icon-edit' */
/* Note: It will also match 'icon-edit' because ' icon-edit' contains ' icon-' */
[class*=' icon-'] {
padding-left: 30px; /* Make space for the icon */
position: relative;
}
[class*=' icon-']::before {
content: '';
position: absolute;
left: 5px;
top: 50%;
transform: translateY(-50%);
width: 20px;
height: 20px;
background-image: url('/path/to/default-icon.svg');
background-size: contain;
}
Styling elements that contain a class name starting with 'icon-' anywhere in their class list
Without the leading space, [class*='icon-']
would match <i class="my-icon-home"></i>
because my-icon-home
contains icon-
. By including the space, [class*=' icon-']
effectively targets class names that are preceded by a space (meaning they are not the first class in the list) or are the first class if the class attribute itself starts with icon-
(e.g., <div class="icon-settings">
). This makes it more robust for targeting specific class tokens within a space-separated list.
[class*=' icon-']
is a common and important technique to ensure you're matching a whole class name, not just a substring within another class name. For example, [class*='btn']
would match mybtn
and btn-primary
, but [class*=' btn']
would only match btn-primary
(if btn
is not the first class) or btn
itself.Comparison and Use Cases
While both selectors deal with class names, their application differs based on the specificity and context required. [class^='icon-']
is best for strict prefix matching, often used for base styles of a component family. [class*=' icon-']
(with the leading space) is more flexible, allowing you to target elements that have a specific class name anywhere in their class
attribute list, making it suitable for utility classes or modifiers that can be combined with other classes.
flowchart TD A[Element with class attribute] --> B{Does 'class' value start with 'icon-'?} B -- Yes --> C["Matched by [class^='icon-']"] B -- No --> D{Does 'class' value contain ' icon-'?} D -- Yes --> E["Matched by [class*=' icon-']"] D -- No --> F[Not Matched]
Decision flow for CSS attribute selectors
Consider the following HTML examples to solidify your understanding:
<div class="icon-home">Home Icon</div>
<span class="button icon-add">Add Button</span>
<p class="text-content my-icon-paragraph">Paragraph</p>
<a class="link icon-external">External Link</a>
Example HTML structure
/* Matches: <div class="icon-home">, <a class="link icon-external"> (because 'icon-external' starts with 'icon-') */
[class^='icon-'] {
border: 1px solid blue;
}
/* Matches: <span class="button icon-add">, <a class="link icon-external"> (because ' icon-external' contains ' icon-') */
/* Also matches <div class="icon-home"> because 'icon-home' contains ' icon-' (implicitly at the start) */
[class*=' icon-'] {
background-color: lightyellow;
}
/* Does NOT match <p class="text-content my-icon-paragraph"> for either selector */
CSS rules demonstrating the effect of each selector on the HTML
[attribute*=value]
selectors. Use them judiciously and profile your CSS if you encounter performance bottlenecks.