HelixOverviewComponentsMapsGraphIntroductionInstallationDeriving a themeSandboxTheme builderVisual testingCortexDocsEngramBuildingTraceBuildingRecallDeclaredServicesInsightsGet in touchSource on GitHub
Theming
Size and densityA control has no size. It takes its height from the region it is in.<helix-flexdata-density="lg"><helix-buttonemphasis="solid"tone="primary">See what is shipping</helix-button></helix-flex>Buttons, inputs, selects, and checkboxes have no size prop.What size is used forSize does three jobs:Emphasis shows which control matters most. The emphasis axis sets it. A
filled primary button marks the important action much more clearly than eight
more pixels of height.Fit depends on the region. A toolbar is tight, a hero is spacious, and a table
row is tighter still. The region sets the fit for every control in it.Optical role applies only to things that are not controls. An avatar at 24 in
a list and at 96 on a profile are two different pictures. That is why
Avatar, Loader, and Orb keep a size.Can two controls differ in height?Ask whether two controls placed together can ever differ in height:Save and CancelAn icon button beside a text buttonAn input and its submit buttonThe two halves of a split buttonIn every case the answer is no.A size on each control describes the region, one element at a time, and
that is how a row ends up with one control at the wrong height. When you set the
density once on the region, you cannot write a row of mismatched heights.Dialog keeps a size by the same test. Two dialogs never sit together. One is
on screen at a time, in the top layer, so the dialog is itself the region.This also helps when you or a model generate code. There is no size to get wrong
on each element, and you make one choice for each region.Set the density of a regionPut data-density on any container, with a value of sm, md, or lg. md
is the default, so you never write it.<helix-toolbar><!-- Nothing here needs a size. The toolbar is already dense. --><helix-button>Run</helix-button><helix-selectlabel="Target"><!-- … --></helix-select></helix-toolbar>Containers that are dense by design set their own density. The app header, the
toolbar, and the announcement all do, so a control inside one of them is already
the right height.Density works through these custom properties:--helix-size-control--helix-size-checkbox--helix-size-switch--helix-size-tagBecause of this, density adds no API to any component, and it passes through
every shadow boundary.The -sm, -md, and -lg tokens are the scale, and they never change. The
unsuffixed tokens hold the current step, and data-density changes them.Exceptionsdata-link-size still exists. A text link has no control height. Its size comes
from typography, and it follows the text around it.A component can still set its own step on the scale. --helix-size-switch is
one step above --helix-size-checkbox at every density, because a switch is a
track with a thumb inside it and a checkbox is a box with a mark in it. The
component sets this once, and it applies to every instance. You do not set a
height on each instance.