CSS code
Cascading Style Sheets (CSS) is a stylesheet language used for describing the presentation of a document written in a markup language such as HTML or XML, including dialects like SVG and MathML.[1] It enables the separation of content from design, allowing web authors to control layout, colors, fonts, and spacing across different media, such as screens, printers, or speech synthesizers.[2] Developed as a core technology of the open web, CSS works alongside HTML and JavaScript to create visually engaging and responsive web pages.[1]
The development of CSS began in October 1994 when Håkon Wium Lie, working at CERN—the birthplace of the World Wide Web—proposed the concept of cascading style sheets to address the limitations of HTML for styling.[3] In collaboration with Bert Bos, the initial specification evolved, leading to CSS Level 1 (CSS1) becoming a W3C Recommendation on December 17, 1996, which introduced basic styling properties like fonts, colors, and margins.[4] CSS Level 2 (CSS2) followed as a Recommendation in May 1998, expanding support for advanced features such as positioned layouts, media types, and international text handling.[5] Subsequent levels, including CSS3 and modular specifications, have continued to evolve the language, with the CSS Snapshot 2025 collecting the current state of all active modules as of September 2025.[6]
CSS operates on a declarative model where styles are defined in rulesets comprising selectors and declarations, applied through cascading and inheritance mechanisms that resolve conflicts and propagate properties to child elements.[2] This "cascading" aspect prioritizes author stylesheets over user or browser defaults, ensuring flexibility in design while maintaining consistency.[7] Today, CSS is essential for modern web development, supporting responsive design via media queries, animations, and grid/flexbox layouts, and is implemented across all major web browsers.[6]
Basic Syntax
Ruleset Structure
A ruleset, also known as a rule, is the fundamental unit of CSS that associates a set of styles with specific HTML elements, consisting of one or more selectors followed by a declaration block enclosed in curly braces.[8] This structure allows authors to target elements and apply properties to them in a declarative manner.[9]
The ruleset begins with the selector portion, which identifies the target elements, followed immediately by an opening curly brace {. The declaration block then resides within these braces, comprising one or more declarations separated by semicolons, and concludes with a closing curly brace }. Selectors can be grouped using commas to apply the same declaration block to multiple targets, such as h1, h2 { ... }.[8] For instance, a simple ruleset might appear as:
css
p { color: black; }
p { color: black; }
Here, p is the selector, { opens the block, color: black; is the declaration, and } closes it.
Within the declaration block, each declaration follows the format of a property name, a colon :, a value, and optionally a semicolon ; at the end. Multiple declarations are listed sequentially, separated by semicolons, with the final semicolon being optional before the closing brace. For example:
css
div {
background-color: white;
font-size: 14px;
margin: 0;
}
div {
background-color: white;
font-size: 14px;
margin: 0;
}
This format ensures that properties like background-color and font-size are applied to the targeted div elements. Omitting required semicolons between declarations can lead to parsing issues, but the last one is permitted for brevity.[10]
User agents handle malformed rulesets robustly to maintain robustness in the face of errors. If a ruleset lacks opening or closing braces, or if declarations are improperly formatted (e.g., missing colons or semicolons), the entire ruleset is typically ignored, while subsequent valid rules continue to be parsed and applied. Invalid values within a declaration cause only that declaration to be skipped, preserving the rest of the block. This error recovery mechanism, defined in the CSS specification, prevents minor syntax errors from breaking the entire stylesheet.[11]
In CSS, comments serve as non-executable annotations that explain code intent, disable sections temporarily, or organize stylesheets without influencing the final rendering. The standard syntax for comments is to enclose text between /* and the nearest subsequent */, allowing both single-line and multi-line usage. For instance:
css
/* This is a single-line comment explaining a rule. */
/*
This is a multi-line comment
spanning several lines
to describe a group of related styles.
*/
/* This is a single-line comment explaining a rule. */
/*
This is a multi-line comment
spanning several lines
to describe a group of related styles.
*/
This syntax is defined in the CSS Syntax Module Level 3, where comments are consumed and discarded during tokenization, ensuring they have no impact on parsing or style application.[12]
CSS comments do not support nesting; the first occurrence of */ terminates the comment, regardless of any intervening /* sequences, which prevents recursive structures and simplifies parsing. An unclosed comment extending to the end of the file triggers a parse error, though browsers typically recover by ignoring the remainder. There are no official single-line comment variants like those in other languages (e.g., //); all comments must use the /* */ delimiters, though short ones can mimic single-line behavior on one line.[12]
Whitespace in CSS includes spaces (U+0020), tabs (U+0009), line feeds (U+000A), and normalized form feeds or carriage returns converted to line feeds during preprocessing. It primarily aids readability through indentation and separation of tokens but is largely ignored by parsers except in specific contexts. For example, multiple consecutive whitespace characters between selectors, properties, or values are collapsed or discarded, as in rule lists or declaration blocks, promoting flexible formatting without semantic changes. However, whitespace is preserved and significant within certain value types, such as in font-family lists (where spaces separate family names) or string literals, to maintain intended structure.[13][14]
Historically, for browser-specific hacks targeting legacy versions of Internet Explorer (e.g., IE 5–9), conditional comments were employed in HTML documents to conditionally include CSS files, rather than directly within CSS code. These non-standard constructs, like <![if IE 8]><link rel="stylesheet" href="ie8.css"><![endif]>, allowed IE to parse and apply targeted styles while other browsers treated them as regular comments. Microsoft deprecated support for conditional comments starting with IE 10, rendering them obsolete for modern development.[15])
Best practices for comments and whitespace emphasize maintainability: use descriptive comments to annotate complex rulesets or sections, such as /* Navigation bar overrides for responsive [layout](/page/Layout) */, to facilitate collaboration and future edits. Avoid over-commenting obvious code to prevent clutter. For whitespace, adopt consistent indentation (e.g., 2 or 4 spaces per level) and line breaks to separate logical groups, enhancing scannability without altering functionality, as excessive or inconsistent spacing can hinder code reviews but holds no rendering impact in most cases.
In CSS, values assigned to properties within declarations follow specific syntactic formats to ensure precise rendering instructions. These formats include keywords, which are predefined identifiers conveying semantic intent; numeric values, representing quantities with optional units; strings, for textual content; colors, for specifying hues and opacities; and functional notations, for dynamic computations. Each format adheres to the CSS syntax rules outlined in the CSS Values and Units Module Level 4 specification, enabling consistent interpretation across user agents.[16]
Keyword values are reserved words that instruct the browser on how to handle a property, often without requiring additional parameters. The keyword none indicates the absence of a value, such as in display: none; to hide an element. Inherit directs the element to adopt the computed value from its parent, promoting stylistic continuity in the document tree. Initial resets the property to its default value as defined in the relevant specification, while unset (introduced in CSS Cascading and Inheritance Level 4) behaves as inherit for inherited properties and initial for non-inherited ones, providing flexible reversion. These keywords are case-insensitive and must appear exactly as specified to avoid parsing errors.
Numeric values in CSS encompass integers (whole numbers like 10), decimals (floating-point numbers like 1.5), and scientific notation (e.g., 1e2 for 100), allowing for precise measurements when combined with units such as px or em. The range and precision of numeric values are implementation-defined, with user agents typically supporting values suitable for typical web development needs, such as 32-bit integers and floating-point decimals. Examples include width: 10px; for an integer with pixels or margin: 1.5em; for a decimal relative to font size. Scientific notation facilitates large or small values, as in font-size: 1e-1rem; equating to 0.1rem, though its use is less common in everyday styling due to readability concerns. These formats ensure scalability in responsive designs.[17]
Strings in CSS are sequences of characters used for content like content properties or attribute selectors, delimited either by double quotes ("text") or single quotes ('text'). Quoted strings preserve whitespace and special characters, such as newlines or quotes (escaped with backslashes), making them suitable for embedding literal text. Unquoted identifiers, conversely, function as strings without delimiters but must avoid CSS-reserved characters like spaces or colons, serving as custom values in properties like font-family: Arial, sans-serif;. The distinction prevents parsing ambiguities, with quoted forms preferred for complex or dynamic content generated via tools like JavaScript.
Color values specify visual tones using multiple formats for versatility. Named colors, such as red or transparent, reference a predefined set of 147 hues from the SVG specification,[18] offering simplicity for basic palettes. Hexadecimal notation uses six digits for RGB components (#rrggbb, e.g., #FF0000 for red) or three for shorthand (#rgb, e.g., #F00), with alpha channels extending to eight digits (#rrggbbaa). Functional notations include rgb(r g b) and rgba(r g b a) for red-green-blue values (0-255 or percentages) with optional opacity (0-1), as in color: rgb(255, 0, 0);. Similarly, hsl(h s l) and hsla(h s l a) use hue (0-360°), saturation and lightness (0-100%), providing intuitive adjustments for designers. These formats support color spaces beyond sRGB in modern browsers, enhancing accessibility and theming.
Functional notations extend value expression through parenthesized functions like calc(), which performs arithmetic on other values. The calc() function supports addition (+), subtraction (-), multiplication (*), and division (/) operators, with parentheses for grouping and operator precedence following standard mathematical rules (multiplication and division before addition and subtraction). For instance, width: calc(100% - 20px); dynamically sizes an element by subtracting a fixed margin from full width, accommodating fluid layouts. Whitespace around operators is optional but recommended for clarity, and the function resolves to a single computed value at parse time. Other functions, such as var() for custom properties, build on this foundation but are detailed elsewhere. This capability, standardized in CSS Values and Units Module Level 3, revolutionized responsive design by enabling context-aware computations without scripting.
Selectors
Element and Universal Selectors
Element selectors, also known as type selectors, target all elements in a document based on their tag name, applying styles to every instance of that element type without regard to position or attributes.[19] The syntax is simply the element name, such as p for paragraphs or div for generic divisions, followed by the declaration block in curly braces.[20] For example, the rule div { color: blue; } styles all <div> elements with blue text color.[21] This foundational selector type enables broad, semantic styling directly tied to HTML structure, targeting elements like headings (h1), lists (ul), or images (img) uniformly across the page.[22]
The universal selector, denoted by an asterisk (*), matches every element in the document tree, serving as a wildcard for global application of styles.[23] It is particularly useful for initializing or resetting default styles, such as *{ margin: 0; padding: 0; } to eliminate browser inconsistencies in spacing.[24] When used alone, it applies rules to all elements indiscriminately, but it can be combined with other simple selectors for broader targeting, though the asterisk is often omitted in such cases for brevity (e.g., *.class is equivalent to .class).[25] This selector promotes consistent baselines in layouts but should be used judiciously due to its broad scope, which can override more specific rules if not managed carefully.[26]
In documents involving namespaces, such as XML or mixed HTML with SVG, both element and universal selectors support prefixes to scope targeting precisely.[19] The syntax uses a vertical bar (|) to separate the namespace prefix from the element name, like svg|circle to select all <circle> elements within the SVG namespace, or ns|* for all elements in a specific namespace ns. Namespaces must be declared using the @namespace at-rule for the selector to resolve correctly, enabling styles in compound documents without unintended cross-namespace matches.[21] For instance, @namespace svg url("http://www.w3.org/2000/svg"); svg|rect { fill: green; } targets only SVG rectangles.[27]
These selectors are limited to direct, type-based matching and do not support descendant, child, or other relational targeting on their own, requiring combinators for more complex patterns.[28] Element selectors were introduced in the CSS Level 1 specification as the primary means of selecting by tag name.[20] The universal selector followed in CSS Level 2, expanding options for comprehensive element selection.[25] Namespace support was formalized in later modules, enhancing compatibility with structured XML environments.
Class, ID, and Attribute Selectors
Class selectors allow styling of HTML elements based on the value of their class attribute, using a period (.) followed by the class name. For instance, the selector .classname targets any element whose class attribute contains "classname" as one of the space-separated tokens. This enables grouping multiple elements for shared styling, such as .button { background-color: blue; } applying to all elements with class="button". In HTML documents, class selectors are equivalent to the attribute selector [class~=classname].[29]
ID selectors provide a means to target a unique element on a page using a hash symbol (#) followed by the ID value. The syntax #idname matches the element with id="idname", which must be unique within the document to conform to HTML standards. ID selectors carry higher specificity than class or attribute selectors, ensuring they override less specific rules in the cascade. For example, #header { font-size: 24px; } styles only the element with id="header".[30]
Attribute selectors offer precise targeting based on any HTML attribute, using square brackets [] enclosing the attribute name and optional value. The basic form [attr] selects elements possessing the attribute regardless of its value, while [attr=value] matches exact equality. More nuanced variants include [attr~=value] for space-separated lists containing the value, [attr|=value] for hyphen-separated lists starting with the value (useful for language codes like "en-US"), [attr^=value] for attributes beginning with the value, [attr$=value] for those ending with it, and [attr*=value] for any substring match. An example is input[type="text"] { border: 1px solid gray; }, which styles text input fields specifically.[31]
Case sensitivity in attribute selectors depends on the document's language: in HTML, attribute names are case-insensitive, but values are case-sensitive unless specified otherwise by the attribute definition; in XML, both are case-sensitive. This ensures consistent matching across document types, such as treating TYPE="text" as matching [type="text"] in HTML but requiring exact casing in XML.[32]
Combinators and Pseudo-Selectors
Combinators in CSS specify relationships between elements in the document tree, enabling more precise targeting of styles beyond simple selectors. They combine two or more selectors, with the combinator placed between them to define how the subsequent selector relates to the preceding one. The four standard combinators—descendant, child, adjacent sibling, and general sibling—are outlined in the CSS Selectors Level 3 specification and have broad browser support across all modern engines, dating back to early implementations in CSS2.
The descendant combinator, represented by a space ( ), selects any element that is a descendant—at any nesting level—of the element matched by the first selector. For example, the selector article p targets all <p> elements inside an <article>, including those nested within other tags. This combinator, introduced in CSS1, is universally supported in browsers since their initial CSS implementations.[33]
In contrast, the child combinator (>) targets only direct child elements of the first selector, ignoring deeper descendants. The selector ul > li, for instance, styles <li> elements that are immediate children of a <ul>, but not those within nested lists. Specified in CSS2 and supported in all major browsers since Internet Explorer 7 (2006), with support in standards mode from IE7 and full support from IE10, it provides finer control over parent-child hierarchies.[34][35]
The adjacent sibling combinator (+) selects an element that immediately follows the first selector as a sibling in the document tree. For example, h2 + p applies styles to a <p> that directly succeeds an <h2> at the same hierarchy level, but not to paragraphs separated by other elements. This combinator, also from CSS2, has full support in modern browsers and since Internet Explorer 7 (2006).[36]
The general sibling combinator (~) extends this by selecting all sibling elements that follow the first selector, not just the immediate one. The selector h2 ~ p, for example, targets every <p> that comes after an <h2> in the same parent container, regardless of intervening siblings. Defined in CSS3 Selectors and supported since Internet Explorer 7, it is now standard across all browsers.[37]
Pseudo-classes, denoted by a single colon (:), augment selectors to match elements based on their state, position, or external factors like user interaction, without altering the document structure. They are detailed in the CSS Selectors Level 3 and Level 4 specifications and enable dynamic styling for user experience enhancements. Most listed pseudo-classes enjoy near-universal support in modern browsers, with origins in CSS2 for interaction-based ones.[38][39]
The :hover pseudo-class applies when a pointing device is over the element, commonly used for interactive feedback like link color changes: a:hover { text-decoration: underline; }. Specified in CSS2 and supported in all browsers since 1999, including early versions of Netscape and Internet Explorer.
The :active pseudo-class matches elements during activation, such as while a mouse button is pressed: button:active { background-color: #ff0000; }. It follows the same CSS2 origins and browser support as :hover, ensuring consistent behavior in user interactions across platforms.
Positional pseudo-classes allow selection based on an element's order among siblings. The :first-child pseudo-class targets the first child of its parent: li:first-child { font-weight: bold; }. Introduced in CSS2 and supported since Internet Explorer 7 (2006), it is now fully implemented everywhere.
The :nth-child(An+B) functional pseudo-class selects elements based on their index, where A and B define a pattern (e.g., :nth-child(2n+1) for odd-positioned items): tr:nth-child(even) { background: #f2f2f2; }. From CSS3 Selectors, it has support in all modern browsers since Internet Explorer 9 (2011).
The :not(selector) pseudo-class excludes elements matching the given selector: input:not([type="hidden"]) { margin: 10px; }. Specified in CSS3 and supported since Internet Explorer 9, it simplifies negation without requiring additional classes.[40]
Pseudo-elements, using double colons (::), generate abstract parts of the document for styling, such as inserted content, and are not actual DOM elements. They adhere to the box model but have limitations like inability to serve as flex or grid containers in some contexts. Defined in the CSS Pseudo-Elements Module Level 4, they originated in CSS2 with single-colon notation for compatibility.[41][42]
The ::before pseudo-element inserts generated content as the first child of the matched element, requiring a content property:
css
q::before {
content: '"';
color: blue;
}
q::before {
content: '"';
color: blue;
}
This adds opening quotes before <q> elements. Supported in all browsers since Internet Explorer 8 (2008) for the single-colon variant, with double colons standard since 2011. Pseudo-elements cannot be direct children targets or have their own pseudo-elements reliably.[43]
Similarly, ::after appends content as the last child:
css
q::after {
content: '"';
color: blue;
}
q::after {
content: '"';
color: blue;
}
It shares the same specification, support profile, and limitations as ::before, enabling symmetrical content insertion like closing quotes.[44]
Properties and Declarations
Common Property Categories
CSS properties are organized into functional categories that address specific aspects of document styling, such as layout, visual appearance, and text rendering. These groupings emerged in the CSS Level 2 Revision 1 (CSS2.1) specification, which established core properties for basic formatting, and were expanded through modular specifications in CSS Level 3 (CSS3) and beyond, allowing for more specialized control over elements. This modular approach, as outlined by the W3C, separates concerns like layout into distinct modules, enabling progressive enhancement without altering foundational behaviors.
Layout properties govern how elements are positioned and arranged within their containers, forming the structural foundation of a page. Key examples include the display property, which determines whether an element generates a block, inline, flex, or grid box, as specified in the CSS Display Module Level 3; the position property, which sets positioning schemes like static, relative, absolute, or fixed, from CSS2.1; and the float property, which allows elements to wrap text by floating to the left or right, also from CSS2.1. Advanced layout options introduced in CSS3 include flex for one-dimensional flexible box layouts via the CSS Flexible Box Layout Module Level 1 and grid for two-dimensional grid arrangements in the CSS Grid Layout Module Level 1. Spacing-related properties like margin and padding further refine layout by adding external and internal space around content, respectively, both defined in the CSS Box Model of CSS2.1. The border property outlines element edges with width, style, and color, contributing to layout boundaries as per CSS2.1.
The box model properties define the dimensions and overflow behavior of elements, treating them as rectangular boxes with content, padding, borders, and margins. Central to this are width and height, which set the content area's size, inherited from CSS2.1's core box model. The overflow property controls how content exceeding the box is handled, such as clipping or scrolling, also from CSS2.1. Additionally, box-sizing specifies whether dimensions include padding and borders (border-box) or only content (content-box), a CSS3 enhancement to the original model for more predictable sizing. These properties interact with layout to ensure elements fit within their contexts without unintended expansion.
Visual properties handle the aesthetic rendering of elements, including colors, backgrounds, and decorative effects. The color property sets foreground text color, a foundational element from CSS2.1. Background styling via the background shorthand applies colors or images, detailed in the CSS Backgrounds and Borders Module Level 3. Rounding corners with border-radius and adding depth via box-shadow are CSS3 additions from the same module, enabling modern visual designs like rounded buttons or elevated cards.
Typography properties manage text characteristics, ensuring readability and stylistic consistency. The font-family property selects typefaces, font-size adjusts text scale, and font-weight controls boldness, all established in CSS2.1's font module. Vertical spacing is handled by line-height, which sets the height of line boxes, while text-align positions text horizontally within its container, both from CSS2.1. Fine-tuning with letter-spacing adjusts space between characters, as defined in the CSS Text Module Level 3.[45]
Transform properties enable geometric manipulations of elements in 2D or 3D space without affecting document flow, introduced in the CSS Transforms Module Level 1. The transform property applies functions like scale() for resizing, rotate() for angular changes, and translate() for positional shifts, all part of CSS3's visual effects expansion.[46] These operate on the element's local coordinate system, preserving layout integrity while altering presentation.
Value Types and Units
In CSS, values assigned to properties are expressed using specific data types and units that define lengths, percentages, colors, and other quantifiable aspects of styling. These ensure precise control over layout, typography, and visual effects, with validation rules enforcing syntactic and semantic correctness to prevent invalid declarations. The CSS Values and Units Module outlines these primitives, where a value must conform to the expected type for the property, such as <length> for dimensions or <color> for hues; non-conforming values are typically ignored by user agents.[47]
Absolute units provide fixed measurements independent of context, often anchored to physical dimensions or device pixels for consistent rendering across media. The pixel unit px serves as the canonical absolute length, defined as exactly 1/96 of an inch at 96 DPI, making it the reference for digital displays. Other units include in (1 inch = 96px), cm (1 centimeter = 96px / 2.54 ≈ 37.8px), mm (1 millimeter = 1/10 cm ≈ 3.78px), and pt (1 point = 1/72 inch ≈ 1.333px). These are validated as non-negative where specified by the property, with negative values clamped or declared invalid to maintain layout integrity.[48]
Relative units adapt to their surrounding context, enabling responsive and scalable designs. The em unit equals the computed font size of the current element, useful for proportional spacing like margins. In contrast, rem references the root element's font size (typically the <html> element), promoting consistent baselines across a document. Percentages % represent a fraction of a reference value, such as the parent block's width for inline elements or the containing block's dimensions for positioning. Viewport-relative units like vw (1% of the initial containing block's width) and vh (1% of its height) tie sizes to the user's screen, ideal for full-width elements. Validation requires a resolvable reference value; if the context is undefined (e.g., no parent width), the unit computes to zero or invalid.[49]
Angle units measure rotational properties, such as in transforms or gradients. Degrees deg complete a full circle at 360, radians rad at 2π (approximately 6.2832), and turns turn at 1, offering intuitive options for developers. These accept positive or negative values unless restricted, with angles normalized by adding or subtracting multiples of 360deg to fall within 0 to 360deg for computation. Time units handle durations in animations and transitions: seconds s for coarse timing and milliseconds ms (where 1s = 1000ms) for precision, always non-negative to avoid reversal effects.[50][51]
The flexible unit fr (fraction) allocates space proportionally in CSS Grid or Flexbox layouts, where multiple fr values share the remaining free space after fixed tracks are placed. For example, grid-template-columns: 1fr 2fr assigns one-third and two-thirds of the available width, respectively; fr must be positive and non-zero, rendering invalid otherwise to prevent division errors.[52]
Core data types underpin these units. A <length> is a <number> followed by an absolute or relative unit (e.g., 5em), or unitless zero; it validates against property constraints, disallowing negatives for sizes like width. <percentage> appends % to a number, scaling relative to a context-specific base, and fails if unresolvable. <color> follows the CSS Color Module's syntax, such as hex (#rrggbb), RGB functions, or named values like red, ensuring valid sRGB or other color spaces. <url> denotes a resource via url("path") or the url() function, validated as a well-formed URI; relative URLs resolve against the stylesheet's base. Functions like calc() extend these by allowing arithmetic combinations, but only among compatible types (e.g., lengths with lengths).[53][54][55]
Shorthand Properties
Shorthand properties in CSS provide a concise way to specify values for multiple related longhand properties within a single declaration, thereby streamlining stylesheet code and enhancing readability. These properties group thematically similar attributes, such as those affecting spacing, borders, or typography, and follow specific syntax rules where the order and number of values determine how they map to individual components. While shorthands simplify authoring, they reset any unspecified sub-properties to their initial values, which can override prior declarations if not intended.[56]
The margin and padding shorthands control spacing around and within elements, respectively, by accepting one to four values that apply to the top, right, bottom, and left sides in clockwise order. For instance, a single value like margin: 1em sets all four margins to 1em, while two values such as [padding](/page/Padding): 1em 2em assign the first to top and bottom and the second to left and right; three or four values follow the pattern top/right-left/bottom or top/right/bottom/left explicitly. Omitted individual properties revert to their initial value of 0 when the shorthand is used.[57][58]
Border shorthands combine width, style, and color specifications for one or all sides of an element's box. The general border property sets uniform values across all sides with syntax allowing one to three components in any order, such as border: 5px solid red, where width defaults to medium, style to none, and color to the element's foreground color if omitted; side-specific variants like border-top follow the same structure. Unspecified components reset to initial values, effectively disabling the border if style is none.[59]
The background shorthand consolidates settings for color, image, repeat, attachment, and position into one declaration, with values provided in flexible order or omission. For example, background: url("image.png") gray 50% [repeat](/page/Repeat) fixed specifies the image source, fallback color, horizontal/vertical centering position, repeating pattern, and fixed attachment to the viewport; any missing component, such as an unspecified repeat, defaults to repeat in both directions, while position defaults to 0% 0% (top-left). This shorthand resets all background longhands to initial values like transparent color or no image if not explicitly set.[60]
Font shorthand addresses typography by combining style, variant, weight, size, line-height, and family in a structured syntax, requiring size and family while optionals precede them. An example is font: italic bold 12px/1.5 sans-serif, which sets italic style, bold weight, 12px size, 1.5 line-height ratio, and sans-serif family; omitted elements like variant default to normal, ensuring a complete font specification without separate declarations. Unspecified longhands reset to initials, such as normal for style and weight.[61]
Transition shorthand enables smooth animations by grouping property, duration, timing function, and delay for changes in response to state alterations. Its syntax allows multiple transitions separated by commas, with a single one like transition: opacity 2s ease 0.5s applying a 2-second ease-timed fade for the opacity property after a 0.5-second delay; the first time value is duration (default 0s), the second delay (default 0s), and timing defaults to ease if absent. Omitted properties or values reset affected longhands to their initials, potentially halting ongoing transitions.[62]
Cascade and Specificity
Cascade Order
The cascade in CSS determines how styles from multiple sources are resolved when they conflict for a given property on an element, establishing a priority order to select the winning value. This process sorts declarations first by their origin and importance, then refines ties using additional criteria such as cascade layers, specificity, and source order. The resulting hierarchy ensures predictable rendering, with later declarations in the source order overriding earlier ones when all other factors are equal—a principle known as the forward cascade.[63]
CSS declarations originate from four primary sources, ordered by descending precedence: user agent (browser defaults), user (custom styles set by the user, such as via browser extensions), author (styles provided by the document creator, including external stylesheets, internal <style> elements, and inline style attributes), and additional transient origins like transitions and animations. Within the author origin, external stylesheets linked via <link> are processed before internal ones, but inline styles are treated as having the highest specificity within that origin. The !important flag elevates a declaration's importance, overriding normal declarations regardless of origin, with the full precedence for important rules being: important user agent > important user > important author.[64][65]
Once origins and importance are accounted for, the cascade evaluates layers—introduced in CSS Cascading and Inheritance Level 5—for declarations within the same origin and importance level. Layers, defined using the @layer at-rule, group styles into named or unnamed tiers; for normal declarations, the last (highest) layer wins, while for !important declarations, the first (lowest) layer takes precedence. Ties within layers are then resolved by specificity (higher specificity wins, as detailed in the Selectors specification) and finally by source order, where later declarations prevail. This layered approach allows authors to control style precedence explicitly without relying solely on specificity.[66][67]
For example, an inline style attribute on an element, such as <p style="color: red;">, will override a conflicting rule from an external stylesheet like p { color: blue; } due to the inline declaration's position in the author origin and its inherent high specificity, demonstrating how source order and origin interact in the forward cascade. Similarly, a user stylesheet with !important will supersede author styles unless the author also uses !important.[68][69]
The cascade order has evolved across CSS levels to address increasing complexity in style management. CSS Level 1 (1996) established the foundational four-step process: importance, origin (author > reader/user > user agent), specificity, and source order, focusing on basic conflict resolution for simple stylesheets. CSS Level 2 (1998) refined this by clarifying imported stylesheet handling and inline precedence but retained the core hierarchy. By CSS Cascading and Inheritance Level 3 (2013), the model incorporated animations and transitions as distinct origins, expanding the precedence to include them after important author rules but before normal author styles, reflecting the growing role of dynamic effects. Subsequent levels, such as Level 5 (2022) for cascade layers and Level 6 (2024) for scoped styles (@scope), introduced additional mechanisms like layers and scoping to provide more granular control over ordering without altering the base origins.[69][70][71]
Specificity Calculation
Specificity in CSS is a mechanism used to resolve conflicts between multiple declarations for the same property on an element by assigning a weight to each selector based on its complexity.[72] This weight, expressed as a four-part tuple (a, b, c, d), determines precedence when declarations have the same origin and importance: a represents inline styles (1 for style attributes, 0 otherwise), b counts ID selectors, c counts classes, attributes, and pseudo-classes, and d counts elements and pseudo-elements. Inline styles effectively receive the highest tuple value of (1,0,0,0), overriding any selector-based rule in the same cascade layer unless !important is used elsewhere.[73]
To calculate specificity for a selector, count the components across the entire complex selector, ignoring the universal selector (*). The tuple is compared from left to right: higher values in a win first, then b, then c, then d; if tied, the last declared rule applies.[74] For example, the selector #id .class yields (0,1,1,0) due to one ID and one class, while div p yields (0,0,0,2) from two element types; thus, #id .class takes precedence. In compound selectors like div#id.class, the counts accumulate to (0,2,1,1).[74]
Pseudo-elements, such as ::before, contribute to specificity as if they were an element selector, adding 1 to the d component (e.g., div::before is (0,0,1,1)).[74] Pseudo-classes like :hover count toward c, similar to classes.[74]
Drafts of Selectors Level 4, part of the broader CSS4 efforts, refined specificity rules for functional pseudo-classes to promote consistency and reduce unintended overrides; for instance, :where() contributes zero specificity (0,0,0,0), while :is() and :not() inherit the highest specificity from their arguments.[75] These changes aim for simpler, more predictable models by minimizing specificity escalation in complex selectors.[74]
Inheritance Model
In CSS, inheritance is the mechanism by which certain property values are automatically propagated from parent elements to their child elements within the document tree, allowing styles to be defined once and applied broadly without explicit repetition.[76] This process uses the computed value of the property from the parent, ensuring that descendant elements receive a default value unless overridden by the cascade or explicit declarations.[76] For the root element of the document, the inherited value defaults to the property's initial value.[76]
Properties in CSS are classified as either inheritable or non-inheritable based on their definitions in the relevant specifications. Inheritable properties, such as color, font-family, and line-height, are those explicitly marked as inherited; child elements default to the parent's computed value for these unless a different value is specified via the cascade. For example, if a parent element has color: blue;, its children will inherit this blue color unless styled otherwise. In contrast, non-inheritable properties, including margin, padding, and border, do not propagate; child elements instead reset to the property's initial value (e.g., margin: 0;) if no applicable declaration exists. This distinction ensures that layout-related properties do not unintentionally cascade, preserving control over box model behaviors.
CSS provides keywords to explicitly control inheritance behavior. The inherit keyword forces a property to take the computed value from its parent element, overriding any default inheritance or cascade result.[77] For instance, color: inherit; on a child explicitly adopts the parent's color, even if the property is non-inheritable by default. The initial keyword resets the specified value to the property's initial value as defined in its specification, bypassing inheritance entirely.[78] Meanwhile, unset behaves contextually: it acts as inherit for inheritable properties and as initial for non-inheritable ones, providing a flexible way to revert to expected defaults.[79]
Inheritance applies recursively to all descendants in the element tree, not limited to direct children, and operates on the flattened tree structure (including shadow DOM where applicable).[76] Inherited values can still be overridden by the cascade, which determines the final computed value based on rule precedence.[80] This model promotes efficient styling by reducing redundancy while allowing fine-grained overrides as needed.
At-Rules and Advanced Constructs
The @media at-rule in CSS enables the conditional application of style rules based on the characteristics of the output device, such as screen size or printing capabilities.[81] This allows developers to create responsive designs that adapt to different media environments without altering the underlying HTML structure. The rule is part of the Media Queries module, which extends the foundational media types defined in earlier CSS specifications.[81]
The syntax for the @media rule is @media <media-query-list> { <style-rules> }, where the media-query-list consists of one or more media queries separated by commas, and the style rules are enclosed in curly braces.[81] Media types specify the target device category and include all (applicable to all devices, the default if omitted), print (for paged media like printers), and screen (for color computer screens); other types such as speech or tty are deprecated in favor of more flexible features.[82] Media features provide finer-grained conditions, testing device properties like width (viewport width), height (viewport height), orientation (portrait or landscape), and resolution (device pixel density); these are expressed as range queries (e.g., min-width: 600px) or boolean checks (e.g., (color) for color-capable devices).[81]
Logical operators combine media queries for complex conditions: and requires all sub-conditions to be true (e.g., screen and (min-width: 600px)), or (via comma separation) applies if any condition matches (e.g., screen, print), and not negates the query (e.g., not print).[81] The only keyword ensures compatibility by hiding styles from user agents that do not fully support media queries.[81] For example, the following applies larger padding on wide screens:
@media screen and (min-width: 600px) {
body { padding: 2rem; }
}
@media screen and (min-width: 600px) {
body { padding: 2rem; }
}
This rule must be placed at the top level of the stylesheet or within supported conditional groups, but not inside other at-rules like @import.[81]
The @supports at-rule, part of the CSS Conditional Rules Module Level 3, allows conditional application of styles based on whether the browser supports specific CSS features.[83] Its syntax is @supports <supports-condition> { <style-rules> }, where the supports-condition can be a declaration (e.g., (display: grid)), selector function (e.g., selector(::backdrop)), or logical combinations with and, or, not. This enables feature detection directly in CSS, providing fallbacks for unsupported properties, such as:
@supports (display: grid) {
.container { display: grid; }
}
@supports (display: grid) {
.container { display: grid; }
}
The @supports rule follows similar placement rules to @media and can nest within other conditional at-rules.
The @import at-rule facilitates modular CSS by importing external stylesheets into the current one, treating their rules as if they were defined inline.[84] Its syntax is @import <url> | <string> [supports(<supports-condition>)]? <media-query-list>? ;, where the URL or string specifies the imported file, optional supports() checks feature availability, and a media-query-list applies conditions similar to @media.[84] For instance, @import url("print.css") print; loads only for print media. Imported stylesheets inherit the cascade origin of the importing sheet but are processed after it in the cascade order.[84]
Placement is critical: @import must appear before all other at-rules (except @charset) and style rules; otherwise, it is invalid and ignored.[84] However, @import can impact performance by requiring synchronous loading of imported files, which blocks parallel downloads and may delay rendering compared to using multiple <link> elements in HTML.[85] As an alternative, HTML <link> tags allow concurrent stylesheet loading for better efficiency.[85]
The @charset at-rule declares the character encoding of the stylesheet, essential for correctly interpreting non-ASCII characters in selectors, values, or content properties.[86] Its syntax is @charset "<encoding-name>" ; (e.g., @charset "[UTF-8](/page/UTF-8)";), and it must be the very first rule in the file, with no preceding bytes, comments, or whitespace; only one is permitted per external stylesheet.[87] The encoding declaration is overridden by any HTTP Content-Type header with a charset parameter, ensuring consistency in network contexts, but it remains useful for local files or when headers are absent.[86]
The @namespace at-rule supports styling XML documents with namespaces, such as XHTML or SVG, by associating a prefix with a namespace URI or declaring a default namespace.[88] The syntax is @namespace <namespace-prefix>? <string> | <url> ;, for example, @namespace svg "http://www.w3.org/2000/svg"; or @namespace "http://www.w3.org/1999/xhtml"; for a default.[88] It must follow all @charset and @import rules but precede other at-rules and style rules; multiple declarations can coexist, with the last one for a prefix taking precedence.[88] This enables qualified selectors like svg|rect to target elements in specific namespaces.[88]
The @layer at-rule, introduced in CSS Cascading and Inheritance Level 5, allows authors to explicitly define and control cascade layers to manage specificity and style precedence without increasing selector complexity.[89] Its syntax includes @layer <layer-name> { <rules> } for named layers or @layer <layer-name1>, <layer-name2>, ...; for declaring layer order. Layers are applied in the order declared, with later layers overriding earlier ones, and unlayered styles falling after all layers. As of September 2025, @layer is widely supported in modern browsers.[6]
Custom Properties and Variables
Custom properties, also known as CSS variables, enable authors to define reusable values within stylesheets, promoting maintainability and dynamic styling. They were introduced in the CSS Custom Properties for Cascading Variables Module Level 1, published as a Candidate Recommendation by the World Wide Web Consortium (W3C) on 3 December 2015.[90] This feature allows for the creation of cascading variables as a primitive value type accepted by all CSS properties, facilitating the substitution of values in declarations to avoid repetition and support theming.[91]
The syntax for defining a custom property involves a name prefixed with two hyphens (--), followed by a colon and the desired value, such as --var-name: value;.[92] These properties can hold any valid CSS value, including tokens, and are case-sensitive, with names supporting alphanumeric characters and hyphens but excluding certain delimiters like colons.[93] To access the value, the var() function is used in place of a property value, with the syntax var(--var-name) or var(--var-name, fallback) to provide an optional fallback.[94] For instance:
:root {
--main-color: #06c;
}
h1 {
color: var(--main-color);
}
:root {
--main-color: #06c;
}
h1 {
color: var(--main-color);
}
This example defines a global color variable at the root level and applies it to an element's color property.[94]
Custom properties operate within the CSS cascade and inheritance model, making them available to an element and its descendants.[95] They are inherited normally, allowing values defined on a parent to propagate to children unless overridden locally.[96] For global scope, properties are often declared on the :root pseudo-class, ensuring availability throughout the document.[94] Local definitions on specific elements limit visibility to that subtree, enabling modular styling. If a custom property is undefined or resolves to an invalid value during computed-value time, the var() function triggers the fallback if provided; otherwise, the dependent property becomes invalid.[97] Cyclic references, where a variable indirectly depends on itself, also result in invalidation.[98]
CSS-wide keywords such as initial, inherit, and unset are supported within custom properties and as fallbacks in var().[99] These keywords are interpreted at the cascaded-value time rather than preserved literally, allowing dynamic resolution based on context—for example, var(--missing, inherit) would inherit the property's value from the parent if the variable is absent.[100] The initial value of any custom property is a guaranteed-invalid token sequence, ensuring it does not inadvertently affect styles unless explicitly referenced.[101]
Keyframes and Animations
CSS animations are defined using the @keyframes at-rule, which specifies the intermediate styles that an element transitions through during the animation sequence. The syntax is @keyframes <keyframes-name> { <rule-list> }, where <keyframes-name> is a custom identifier or string, and the rule list consists of keyframe selectors such as from (equivalent to 0%), to (equivalent to 100%), or percentage values between 0% and 100% that mark points along the animation timeline.[102] For example:
css
@keyframes slide-right {
from { margin-left: 0px; }
50% { margin-left: 110px; }
to { margin-left: 200px; }
}
@keyframes slide-right {
from { margin-left: 0px; }
50% { margin-left: 110px; }
to { margin-left: 200px; }
}
This defines an animation named slide-right that shifts the left margin progressively. Keyframe selectors with invalid values, such as percentages outside 0-100%, are ignored during rendering.[103]
The animation property serves as a shorthand for applying these keyframe-defined animations to elements, combining multiple longhand properties into a single declaration. Its syntax is animation: <single-animation>#, where each <single-animation> can include the animation name, duration (a <time> value like 2s), timing function (e.g., ease, linear, or cubic Bézier functions like ease-in-out), delay (another <time> value, defaulting to 0s), iteration count (a number, infinite, or default 1), and direction (normal, reverse, alternate, or alternate-reverse, defaulting to normal).[104][105] For instance:
css
div { animation: slide-right 2s ease-in-out 1s 3 alternate; }
div { animation: slide-right 2s ease-in-out 1s 3 alternate; }
This applies the slide-right animation to all div elements, lasting 2 seconds with an ease-in-out timing function, starting after a 1-second delay, repeating 3 times, and alternating direction on each iteration. Negative delays cause the animation to begin partway through its timeline.[106]
To apply an animation, the animation-name property (or the shorthand) is set on a selector, linking it to the corresponding @keyframes rule; without a matching name, no animation occurs. Animatable properties within keyframes, such as transform for scaling or rotating elements, allow for complex motion effects like sliding or fading.[107]
CSS animations can be controlled programmatically via the Web Animations API (WAAPI), where JavaScript methods like element.getAnimations() retrieve CSS-defined animations as Animation objects, enabling code-based pausing or reversal without altering the stylesheet. For example, after applying animation: slide-right 2s;, JavaScript can invoke animation.pause() to halt it mid-sequence.[108]
For legacy browser support, particularly older WebKit-based browsers, vendor prefixes such as -webkit-@keyframes and -webkit-animation were historically required alongside unprefixed versions to ensure compatibility.
Integration and Best Practices
Linking CSS to HTML
CSS can be associated with HTML documents through three main methods: linking external stylesheets, embedding internal styles, and applying inline styles. Each approach serves different needs, with external linking favored for reusability across multiple pages, internal embedding for document-specific styles, and inline styles for targeted overrides. These methods originate from the author level in the CSS cascade, where author-specified rules take precedence over user agent defaults but can be influenced by specificity and order.
External stylesheets are linked using the <link> element, typically placed in the <head> section of the HTML document. The rel attribute is set to "stylesheet" to indicate the relationship, while the href attribute provides the URL or path to the CSS file. For example:
html
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="styles.css">
This method enables the reuse of a single stylesheet across multiple HTML files, promoting maintainability. The media attribute allows conditional application based on device characteristics, such as <link rel="stylesheet" href="print.css" media="print"> for print-specific styles or <link rel="stylesheet" href="mobile.css" media="screen and (max-width: 600px)"> for responsive designs. The title attribute can define a stylesheet set name for alternate styles, enabling user or browser selection among options like default or high-contrast themes.
Internal styles are embedded directly in the HTML using the <style> element, which must be placed within the <head> section to conform to standards. This element contains CSS rules that apply to the entire document. An example is:
html
<head>
<style>
body { font-family: Arial, sans-serif; }
h1 { color: navy; }
</style>
</head>
<head>
<style>
body { font-family: Arial, sans-serif; }
h1 { color: navy; }
</style>
</head>
Styles from <style> elements are global and affect the whole document unless limited by media queries via the media attribute, such as <style media="screen">. A scoped attribute was historically proposed to restrict styles to the parent element and its subtree, but it is not included in the current HTML specification and lacks browser support. However, as of 2025, the CSS @scope at-rule enables local scoping of styles within specific DOM subtrees, including for internal styles, without requiring shadow DOM.[109]
Inline styles are applied using the style global attribute directly on HTML elements, allowing CSS declarations specific to that element. For instance:
html
<p style="color: red; font-weight: bold;">This text is red and bold.</p>
<p style="color: red; font-weight: bold;">This text is red and bold.</p>
This approach overrides other styles for the element but is generally discouraged for production use, as it intermingles presentation with content and complicates maintenance; it is better suited for prototyping or unique overrides.
Although external stylesheets can alternatively be imported via the CSS @import at-rule (e.g., @import url("additional.css"); at the top of a primary stylesheet), this method differs significantly from <link> in loading dynamics. @import enforces sequential loading of imported files, which can block rendering and degrade performance by preventing parallel downloads, whereas multiple <link> elements enable concurrent loading for faster page rendering. For optimal performance, <link> is recommended over @import when associating stylesheets in HTML.
Regarding precedence in the CSS cascade, within the author origin, inline styles via the style attribute hold the highest priority, followed by rules from internal <style> elements (ordered by their appearance in the document), and then external stylesheets (linked via <link> or imported, ordered by inclusion and cascade layers). This hierarchy ensures that more directly applied author styles supersede broader ones, though specificity and !important declarations can further influence resolution.
Debugging and Validation
Debugging CSS involves systematically identifying and resolving issues in stylesheets that prevent intended rendering, while validation ensures adherence to standards for compatibility and maintainability. Browser developer tools, integrated into modern web browsers like Chrome, Firefox, and Edge, serve as primary aids for real-time inspection and correction. The Elements or Inspector panel allows developers to select HTML elements and view applied CSS rules, including inherited and overridden properties, facilitating live editing to test changes instantly without altering source files.[110] The Computed styles view displays the final resolved values for each property after cascade and specificity resolution, helping pinpoint discrepancies between authored and rendered styles.[111] Additionally, the browser console logs CSS-related errors, such as syntax issues or unsupported properties, providing immediate feedback during development.[112]
Validation services like the W3C CSS Validator check stylesheets against official specifications, identifying syntax errors, invalid selectors, and deprecated properties to promote standards compliance. Users can validate by URI, file upload, or direct input, with the tool reporting conformance levels for CSS versions from 1 to the latest modules.[113] It flags issues such as unrecognized at-rules or properties not yet standardized, ensuring code remains future-proof as browser implementations evolve.[114]
Common CSS errors often stem from invalid values, where properties receive unsupported inputs like width: auto 50px; instead of a single valid unit, causing the entire declaration to be ignored by parsers. Missing units, such as specifying margin: 10; without px or em, lead to parsing failures since most length properties require explicit units per the CSS Values and Units specification. Specificity wars arise when multiple rules target the same element with conflicting declarations, resolved by the browser's specificity algorithm that prioritizes inline styles (1,0,0,0) over IDs (0,1,0,0), classes (0,0,1,0), and elements (0,0,0,1), potentially overriding intended styles unexpectedly.[115][116]
Linting tools enhance code quality by enforcing rules beyond basic validation. Stylelint, a customizable linter for CSS and related languages, detects errors like duplicate properties or invalid vendor prefixes while allowing configuration of over 100 rules for team conventions, such as ordering declarations alphabetically.[117] Prettier, an opinionated code formatter, automatically reformats CSS for consistent indentation, semicolon usage, and bracket placement, integrating seamlessly with editors to run on save and reduce style-related disputes.[118]
Cross-browser testing verifies feature support across environments to catch rendering differences. The Can I use... database provides detailed support tables for CSS properties, selectors, and at-rules, indicating global usage percentages and polyfill needs, enabling developers to apply fallbacks like feature queries (@supports) for unsupported features.[119]
Optimizing CSS for performance is essential to ensure efficient rendering and responsiveness in web applications. Browsers process CSS by constructing the CSS Object Model (CSSOM), which combines with the Document Object Model (DOM) to form the render tree; this tree then undergoes layout (reflow) and painting (repaint) stages to display content. Inefficient CSS practices can prolong these stages, increasing load times and jank during interactions.[120]
To minimize reflows and repaints, developers should avoid frequent changes to properties that trigger layout recalculations or visual updates, such as width, height, or margin during animations. Reflow occurs when the browser recomputes element positions and sizes, often cascading to parent and sibling elements, while repaint follows to redraw affected pixels. Overuse of position: absolute can help by removing elements from the normal document flow, thus limiting reflow scope, but excessive reliance may lead to unpredictable layouts and increased complexity in style matching. Similarly, complex selectors exacerbate style resolution time by requiring deeper DOM traversal.[121]
Efficient selector design prioritizes simplicity to accelerate CSS matching. For instance, a direct class selector like .headline processes faster than a descendant chain such as body div#main-content article.post h2.headline, as the latter demands ancestor-descendant checks across the DOM tree. While the performance difference is typically in microseconds, it compounds in large stylesheets or dynamic content. Best practice involves favoring ID or class selectors over universal (*) or attribute-based ones, which inflate the selector engine's workload.[120][122]
Reducing CSS file size enhances download and parsing speed. Minification removes whitespace, comments, and redundant characters, often shrinking files by 20-30% without altering functionality; for example, merging duplicate rules like h1 { color: #000; } and h2 { color: #000; } into h1, h2 { color: #000; } further optimizes bytes. Complementing this, tools like PurgeCSS scan HTML and templates to eliminate unused rules, preventing bloat from framework-generated code (e.g., Bootstrap's full stylesheet); this not only cuts network transfer but also streamlines render tree construction by excluding irrelevant styles. Compression via gzip can amplify savings, targeting files under 14 KB for critical paths.[123][124]
Strategic loading mitigates render-blocking behavior, where external CSS halts initial painting. Inlining critical CSS—styles for above-the-fold content—directly in the HTML <head> via <style> tags eliminates round-trip requests, improving First Contentful Paint (FCP) by up to 20-30% on high-latency networks. Non-critical CSS should load asynchronously, such as by setting <link rel="stylesheet" media="print"> initially and switching to media="all" via JavaScript, or using preload with as="[style](/page/Style)" to hint priority without blocking. This approach ensures progressive rendering while deferring less urgent styles.[125][126]
For animations, leveraging GPU acceleration promotes smoother execution by offloading work from the CPU. Properties like transform (e.g., translateX(), scale()) and opacity trigger compositing layers, allowing hardware-accelerated rendering without reflow or repaint; a simple example is:
css
.element {
transition: [transform](/page/Transition) 0.3s ease, opacity 0.3s ease;
}
.element:hover {
[transform](/page/Transition): translateX(10px);
opacity: 0.8;
}
.element {
transition: [transform](/page/Transition) 0.3s ease, opacity 0.3s ease;
}
.element:hover {
[transform](/page/Transition): translateX(10px);
opacity: 0.8;
}
In contrast, animating layout properties like top or left forces reflows, potentially dropping frame rates below 60 FPS. The will-change property (e.g., will-change: [transform](/page/Transition);) can hint browsers to prepare layers, but overuse increases memory consumption. Animations remain performance-heavy, so limit them to essential interactions.[127][122]