List of Properties Allowed and Dark Mode
This section lists the CSS properties the validator accepts and explains how to write dark mode, pseudo-class, pseudo-element, and responsive rules in custom CSS.
Allowed Properties
Only the following properties are accepted. Any property not in this list causes a validation error.
Typography
color, font-family, font-size, font-weight, font-style, letter-spacing, line-height, text-align, text-decoration, text-decoration-color, text-decoration-style, text-indent, text-overflow, text-shadow, text-transform, vertical-align, white-space, word-break, word-spacing, list-style, list-style-type, and list-style-position.
Background and borders
background-color, background (no url()), border, border-*, border-radius, outline, outline-*, and box-shadow.
Spacing and sizing
padding, padding-*, margin, margin-*, gap, row-gap, column-gap, max-width, min-width, max-height, and min-height.
Visual effects
opacity, transform, transition, box-shadow, visibility (only visible; hidden is blocked), cursor, pointer-events, and accent-color.
Flex layout
flex-direction, flex-wrap, flex-grow, flex-shrink, flex-basis, align-items, align-self, justify-content, justify-self, and order.
Media and SVG
object-fit, object-position, fill, stroke, and stroke-width.
CSS custom properties
--any-name is always allowed. Custom properties are inert on their own and only take effect when consumed via var(), so they carry no layout risk. This is the recommended approach for theming components that use CSS variables internally.
Blocked properties
These are rejected regardless of value: position, display, width, height, z-index, overflow, float, content, animation, and animation-*.
Blocked values
url() is blocked in any property value. This prevents loading external images via background, background-image, cursor, and similar. visibility: hidden is blocked; visibility: visible is fine.
Blocked at-rules
@import, @font-face, and @keyframes are blocked. Use @media and @supports freely.
Value functions
calc(), clamp(), min(), and max() are allowed in any property value. Use them freely for responsive sizing:
.sp-sidenav { max-width: clamp(200px, 20vw, 280px); }
.sp-product-tile { padding: calc(var(--tile-padding, 16px) * 1.5); }var() is allowed anywhere a value is accepted. Custom properties defined on an ancestor element resolve correctly in descendant rules.
Dark mode
The portal supports light, dark, and system (operating system preference) modes. The .dark class is toggled on the root html element by the mode toggle in the profile menu.
Write dark variants using .dark as a leading class:
.sp-topbar { background-color: #004831; }
.dark .sp-topbar { background-color: #003828; }The scoping transformer handles .dark correctly. It inserts the scope between .dark and the rest of the selector, so the final injected rule is:
.dark body.sp-consumer .sp-topbar { background-color: #003828; }You do not need to do anything special. Write .dark .sp-* as you normally would.
Pseudo-classes and pseudo-elements
Pseudo-classes (:hover, :focus, :active, :nth-child(), [aria-selected="true"], and similar) and pseudo-elements (::before, ::after) are fully supported, as long as the selector contains at least one allowed .sp-* class:
.sp-product-tile:hover { box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2); }
.sp-sidenav-item--active .sp-sidenav-item-bg div { color: #367a91; }
.sp-search-modal-tabs button[aria-selected="true"] span { color: #004831; }
.sp-markdown-content tr:nth-child(odd) { background-color: #f7f7f7; }Responsive design
@media blocks are fully supported. Wrap rules inside a media query as normal:
@media (max-width: 768px) {
.sp-sidenav { padding: 8px; }
}@media and .dark can be combined. Write them as nested rules:
@media (max-width: 768px) {
.sp-sidenav { padding: 8px; }
.dark .sp-sidenav { background-color: #0e1e18; }
}