Controlling Mixins with Conditional Logic in Stylus Variables and Composites Guide
Controlling Mixins with Conditional Logic in Stylus Variables and Composites Guide
Implementing dynamic style switching in the Stylus CSS preprocessor is a key capability for building responsive designs and theming systems. Unlike traditional JavaScript conditional statements (such as if/else if), Stylus offers unique syntax sugar based on attribute selectors to simulate control flow. Its core lies in leveraging pseudo-classes like [attr], :hover, :active, along with variable interpolation, to generate corresponding CSS rules at compile time based on specific conditions. This mechanism allows developers to perform complex logical judgments and mixed execution flows using pure style languages without introducing additional scripts.
The most fundamental logic control mechanism in Stylus involves detecting element states or environmental changes through attribute selectors. When an element's attribute meets a specific condition, the preprocessor automatically applies the corresponding rule block. This mechanism is commonly used to handle media queries, user interaction feedback, and dynamic data injection scenarios. For example, it can determine whether to apply specific transition effects by checking the value of the data-type attribute, or adjust global variables based on browser characteristics (such as prefers-color-scheme: dark).
// Example: Enable dark mode styles when the element has the data-mode="dark" attribute
[data-mode='dark']
background #1a1a2e
color #f0f0ff
// Further nested condition to check brightness value (requires external JS injection or more complex logic)
[data-brightness > '50%']
font-size +px(0.8)
The above code demonstrates how attribute matching serves as a trigger for the "true" condition. If the element does not meet this attribute, the default styles take effect; conversely, if the condition holds, all declarations within the block are executed. This one-way conditional judgment is the fundamental unit for building mixed logic.
Nested Structures and Multi-branch Decision Chains
In practical applications, a single condition is often insufficient to handle complex business scenarios, so it is necessary to master multi-level nesting and shorthand syntax similar to "ternary operators" to implement multi-branch decisions. Stylus supports defining new conditional blocks within rules, forming a hierarchical structure similar to if-else-if. Additionally, utilizing variable assignment statements (such as $var = condition ? value1 : value2) can greatly simplify logical expressions, achieving true ternary judgments.
// Example: Simulating a multi-branch decision chain
.container
width: $w
// First-level condition: Set base width based on container type
[data-type='flex']
width calc(100% - 2rem)
[data-type='grid']
width 80vw
// Second-level nesting: Further judge direction in grid mode
&.vertical
display flex-direction column
// Ternary operator example (requires variable usage)
$bg-color = (darkMode ? '#333' : '#fff')
body
background $bg-color
[data-theme='light']
color #000
[data-theme='dark']
color #eee
From the above code, it can be seen that nested structures allow us to apply different logical rules at various levels. Meanwhile, ternary operators provide a declarative way of judgment, converting complex conditional expressions directly into variable values, avoiding the repetitive writing of lengthy style blocks. This is particularly efficient for handling mixed execution of multiple mutually exclusive conditions.
Combining Pseudo-classes and Interaction States
In addition to static attribute matching, pseudo-class selectors in Stylus (such as :hover, :focus, :active) are also an important part of conditional judgments. In actual projects, user behavior states are often combined with other dynamic data to achieve refined interaction feedback. For example, a button may change color on hover, but if it is in a disabled state, this change is ignored; or the duration of an animation can be determined based on the data attributes of the currently focused element.
.button
padding: 1rem 2rem
border-radius 4px
// Basic hover effect
:hover:not([disabled])
background #007bff
[data-transition='fast']
transition-duration 0.3s
[data-transition='slow']
transition-duration 1s
// Combined condition: Show tooltip only when the element is focused and has a specific data marker
[data-tooltip]:focus:not([hidden])
box-shadow 0 4px 6px rgba(0,0,0,0.3)
In this example, we see the "and" relationship of multiple conditions (not(), combined selectors). :hover:not([disabled]) ensures that the hover effect is triggered only when the element is not disabled. This ability for combined judgments allows Stylus to simulate extremely rich interaction logic without needing to write additional JavaScript code to achieve conditional style switching.
Best Practices: Maintaining Clarity and Performance Considerations
Although Stylus's conditional judgment mechanism is flexible and powerful, abusing it in large projects can lead to bloated CSS file sizes and maintenance difficulties. Developers should adhere to the following principles to optimize mixed execution strategies:
- Prioritize Variables: Encapsulate complex boolean expressions into variables (such as
$isDark = true) to improve code readability and reduce redundant calculations. - Avoid Over-nesting: When condition levels exceed two layers, it is recommended to consider extracting independent modules or using CSS Modules for isolation.
- Leverage Pre-compilation Features: Stylus merges all matching rule blocks into the output at runtime; therefore, inactive condition blocks do not consume browser performance but increase CPU overhead during the parsing phase.
By reasonably utilizing attribute selectors, nested structures, and ternary operators, developers can build dynamic style systems that are both efficient and highly maintainable. Mastering these techniques not only improves development efficiency but also empowers CSS itself to become a powerful tool for logical control.