Layout · Float

Float

CSS-float primitive: pulls a child to the start or end of the text flow so the surrounding inline content wraps around it. Composes through <Box>, so every Box prop (max-width, padding, margin, …) still works. Typical uses: inline images, pull-quotes, drop caps. Uses logical float: inline-start / inline-end so the primitive mirrors automatically in RTL. Note: this is NOT the legacy 9-zone absolute-positioning Float — see the README's Baseline section for the design history.

parts{compiled.parts.order.length} events0 extendsBox scopeeidos
{#if demo === 'image'}
{childWidth}×{Math.round((childWidth * 3) / 4)}
{:else if demo === 'pull-quote'}
"A short quotation pulled from the surrounding text to anchor the reader's attention."
{:else} {/if}
{#if demo === 'drop-cap'} ndon a moment to consider how the CSS `float` property has shaped the layout of long-form articles for two decades. Originally designed exclusively to allow text to flow around an image, it became the de-facto positioning tool of the early web. Today it has fallen out of favour for general layout, replaced by flex and grid, but it remains the right answer for the narrow editorial case it was built for. {:else} Long-form prose flowing around the floated child. CSS `float` predates flex and grid by two decades; it was originally designed exclusively to allow text to wrap around an inline image. For modern layout, prefer <Flex> / <Grid>; for inline editorial wraps — pull-quotes, sidebar notes, drop caps — the CSS-`float` primitive is still the right tool. The Float wrapper provides logical-side semantics so the same markup mirrors automatically in RTL contexts. {/if}
trace {trace.length === 0 ? 'no semantic events' : `${trace.length} event(s)`} · side {side} gap {gap} · maxWidth {childWidth}px
{#if tab === 'live'}

Controls

Float is eidos-native — no soma split. The side prop drives the logical float direction; gap sets the inline margin against the wrapped text.

eidos props · visual treatment
soma n/a · float is eidos-native — equivalent markup shown svelte
{somaSnippet}
eidos visual · side / gap + inherited Box props svelte
{eidosSnippet}
{/if} {#if tab === 'api'}

API reference

Two props on the root + every Box prop inherited. The block-axis margin (top / bottom) lives on the standard marginTop / marginBottom from Box, because real-world floats often need a small padding-top to align with the ascender of the surrounding text.

Float props
PropTypeNotes
side {sides.join(' | ')} Logical side. Maps to float: inline-start / inline-end. Mirrors in RTL. Default start.
gap number | string Inline margin against the wrapped text. Number → var(--space-N). Default 3.
Inherited from Box
PropTypeNotes
maxWidth / width / minWidth number | string Constrain the float's inline size — essential for readable wrap behaviour.
marginTop / marginBottom number | string Block-axis margin against the surrounding text.
padding number | string Inner padding (e.g. for pull-quote boxes).
… BoxProps See <Box>. Note: position is excluded — Float uses the cascade's `float`, not absolute positioning.
Reference comparison
LibraryClosest equivalentDifference
radix-themes <Inset> Radix Inset takes 4 physical sides; UIX Float uses logical start / end so it mirrors in RTL.
mui Pull-quote pattern MUI documents the pattern with manual float: left styling; UIX wraps it as a typed primitive with logical sides.
mantine n/a Mantine ships no float primitive; consumers write style={`{{ float: 'left' }}`} manually.
{/if} {#if tab === 'morfo'}

Morfo contract

FieldValue
name{floatMorfo.name}
kebab{floatMorfo.kebab}
scope{floatMorfo.scope.join(', ')}
parts{partsList.length}
events0
Parts
{#each partsList as part} {/each}
kebab marker element archetype optional
{part.kebab} [{part.marker}] <{part.defaultElement}> {part.archetype} {part.optional ? 'yes' : 'no'}

Float declares a single Provider part. The recipe reads data-side to pick the logical float direction; the --float-gap variable controls the inline margin against the wrapped text.

{/if} {#if tab === 'sema'}

sema · events

Float declares no semantic events. As a passive layout primitive, it changes how its child participates in the surrounding text flow and nothing else. Animations on float direction changes (e.g. switching side) belong to the consumer's transition logic, not to Float itself.

{/if} {#if tab === 'recipe'}

Eidos recipe

Recipe lives in src/uix/eidos/components/float/float.css. The data-side attribute switches between float: inline-start and float: inline-end; the inline margin against the text sits on the side that faces the wrapped content.

SelectorOwnerPurpose
[data-float] morfo Provider marker. Emitted on top of the Box shell.
{`[data-box][data-float] { float: inline-start; margin-inline-end: var(--float-gap, var(--space-3)); }`} eidos Default side — float to start of text flow.
[data-box][data-float][data-side='end'] eidos Override — float to end of text flow with mirrored gap.
{/if} {#if tab === 'a11y'}

Accessibility

ConcernContract
Role None implicit. Default element is <div>. When the float holds a quote, wrap the inner content in <blockquote>; when it holds an image, the consumer supplies alt.
Reading order The floated element appears in DOM order but visually wraps with surrounding text. Screen readers respect DOM order; consider placing pull-quotes after the paragraph they belong to if visual order matters.
Keyboard Float is not focusable. Tab order follows DOM children.
Focus visible Float does not paint a focus ring.
RTL side='start' mirrors automatically — in RTL the float pulls to the right side. Use logical sides; avoid hardcoded float: left / right.
{/if}