Skip to content

phil/ux-css

alpha

phil-ux, the CSS framework of PHIL: real, mostly classless CSS with --phil-* tokens, light and dark.

phil-ux dresses the HTML elements without a class first — the page, its typography, forms as Symfony renders them, buttons, tables, dialogs, disclosures, navigation, gauges and popovers — and adds classes that say what an element is or has, in camelCase: isSplit, isDanger, hasIcon. It is plain CSS in cascade layers, with no build step and no Tailwind: a site's own styles, written outside any layer, win over it without !important.

Every value is a token. The scales are named in t-shirt sizes and follow global multipliers. The colours come from an OKLCH palette numbered by lightness, and components read colour roles — a fill, a border and the colour on that fill, each quiet or loud —, never the palette. One theme holds light and dark in the same declarations; the page follows the system unless data-theme chooses. The package also ships the PHP contrast rule the theme is tested against, which a site runs on its own overrides.

The recipes of the PHIL UX kit for the Symfony UX Toolkit take their look from this stylesheet.

Status

PartWhat it isStatus
Tokens: dimensionsSpace, text, radius, shadow in t-shirt sizes, fonts, motion, global multipliersImplemented and tested
Tokens: paletteSeven OKLCH hues numbered by lightness, in sRGBImplemented and tested
Tokens: colour rolesSurface, text, link, focus; the fill/border/on × quiet/loud grid of six roles; light and darkImplemented and tested
Classless baseTypography, page elements, focus ring, forms and Symfony's form markup, buttons, tables, dialogs, disclosures, navigation, gauges, popovers, reduced motionImplemented and tested
LayoutisStack, isCluster, isGrid, isCenter, isNarrow, isSplit, isFullHeight, isCover, isBleed, hasEntranceImplemented
Display componentsisEyebrow, isHeadline, isReveal (the clip reveal), isLogo, isProse, isReaction, isReactionPickerImplemented
Tones and sizesisPrimary, isNeutral, isDanger, isSuccess, isWarning, isInfo, isSmall, isLargeImplemented and tested
Button looksisButton, isSecondary, isGhost, isOutline, isLoading, hasIcon, isIconOnly, isButtonGroupImplemented and tested
Interface componentsisBadge, isAlert, isCard, isEmptyState, isTabs, isSheet, isSwitch, isTooltip, isDropdown, isAccordion, isBreadcrumb, isPagination, isStepper, isCarousel, isSpinner, isSkeleton, isAvatar, isSeparator, isActivityCalendar, isQrCode, isField, isItem, isToggle, isRadioGroup, isScrollArea, isAspectRatio, isCollapsible, isKbdGroup, isChart, isLoginForm, isSignupFormImplemented and tested
Highlighted code, print fallbackThe hl-* classes in colour roles; .ujo-print-fallback shown only on paperImplemented and tested
Symfony Flex recipeIn the recipes repository of PHIL: maps dist/ in AssetMapperImplemented
UtilitiesisVisuallyHidden, isSkipLink, isMuted, isGrowImplemented
dist/phil-ux.cssThe single-file build, its freshness testedImplemented and tested
ContrastRule, TokenSheet, OklchThe contrast rule, checked on the package's tokens and on a site's overridesImplemented and tested

Documentation

DocumentWhat it covers
InstallationAssetMapper, npm, a copied file; the cascade layers.
TokensThe scales, the palette, the colour roles, and the tokens as DTCG JSON for design tools.
ThemesLight and dark, data-theme, a site's overrides.
ElementsWhat the classless base dresses, forms and Symfony's markup included.
LayoutThe layout classes.
ComponentsTones and sizes, buttons, every component, the utilities.
The contrast ruleThe rule, and how a site checks its overrides with it.
Extension pointsWhat a site changes, and how.
TestingHow the package is tested.
ReferenceEvery file and type of the package.

Quick start

<html lang="en" data-theme="dark">
<link rel="stylesheet" href="/styles/phil-ux.css">

<div class="isSplit isFullHeight">
    <div class="isCover">
        <header>…</header>
        <main class="isCoverBody">
            <hgroup>
                <p class="isEyebrow">Coming soon</p>
                <h1 class="isHeadline">Studio</h1>
            </hgroup>
        </main>
    </div>
    <figure class="isBleed hasEntrance"><img src="/images/main.png" alt=""></figure>
</div>

Requirements

A browser of 2024 or later, for cascade layers, light-dark(), oklch() and :user-invalid; the animation of details and of the top layer come with the browsers that have them, and the rest works without. PHP 8.5 or later for the contrast rule, with no extension.

Contributing

Contributions are welcome on the PHIL monorepo: read the contribution guide and the code of conduct. Report a vulnerability privately, as the security policy explains, never in a public issue.

License

MIT, © Philippe Gamache, doing business as Le Gnome Archiviste; a Parler Haut Interagir Librement project. See LICENSE.