Default Components Sizing
Learn how to size AudioUI's default components using the built-in size system, from base units to multipliers, aspect ratios, and fixed vs adaptive sizing.
AudioUI's default components (Knob, Slider, Button, CycleButton, Keys) use a base unit system for consistent sizing. This system ensures mathematical harmony between components and provides both fixed and adaptive sizing options.
Note: This sizing system applies to AudioUI's built-in default components. Fully customized components built with Control Primitives and custom view components use their own independent sizing systems.
Overview
The size system provides:
- Consistent sizing: All components derive from a single base unit
- Mathematical harmony: Components align perfectly in layouts
- Flexible sizing: Choose between fixed sizes or adaptive container-filling
- Themeable: Scale the entire system by changing the base unit
Base Unit System
All component sizes derive from a single base unit:
- Base Unit:
--audioui-unit(default: 48px) - Size Multipliers:
xsmall: 1x base unit (48px)small: 1.25x base unit (60px)normal: 1.5x base unit (72px) - defaultlarge: 2x base unit (96px)xlarge: 2.5x base unit (120px)
CSS Variable Structure
Size dimensions are defined using CSS variables:
/* Base unit */
--audioui-unit: 48px;
/* Size multipliers */
--audioui-size-mult-xsmall: 1;
--audioui-size-mult-small: 1.25;
--audioui-size-mult-normal: 1.5;
--audioui-size-mult-large: 2;
--audioui-size-mult-xlarge: 2.5;
/* Square components (Button, Knob, CycleButton) */
--audioui-size-square-{size}: calc(var(--audioui-unit) * var(--audioui-size-mult-{size}));
/* Horizontal Slider (1x2) */
--audioui-size-hslider-height-{size}: calc(var(--audioui-unit) * multiplier);
--audioui-size-hslider-width-{size}: calc(height * 2);
/* Vertical Slider (2x1) */
--audioui-size-vslider-width-{size}: calc(var(--audioui-unit) * multiplier);
--audioui-size-vslider-height-{size}: calc(width * 2);
/* Keys (1x5) */
--audioui-size-keys-height-{size}: calc(var(--audioui-unit) * multiplier);
--audioui-size-keys-width-{size}: calc(height * 5);Component Aspect Ratios
Each component type has a fixed aspect ratio that defines its shape:
- Button, Knob, CycleButton: 1x1 (square)
- Horizontal Slider: 1x2 (width:height) - width > height
- Vertical Slider: 2x1 (width:height) - height > width
- Keys: 1x5 (width:height) - width > height
These aspect ratios are preserved at all sizes, ensuring components maintain their visual identity.
Fixed Sizing
When adaptiveSize={false} (default), components use fixed sizes based on the size prop:
import { Knob, Slider } from "@cutoff/audio-ui-react";
export default function FixedSizingExample() {
return (
<div style={{ display: "flex", gap: "20px", alignItems: "flex-end" }}>
<Knob value={0.5} onChange={(e) => {}} label="Small" size="small" />
<Knob value={0.5} onChange={(e) => {}} label="Normal" size="normal" />
<Knob value={0.5} onChange={(e) => {}} label="Large" size="large" />
<Slider
value={0.5}
onChange={(e) => {}}
label="Slider"
size="normal"
orientation="horizontal"
/>
</div>
);
}How Fixed Sizing Works
- CSS Classes: Size class is applied for semantic purposes and external styling
- Inline Styles: Size dimensions are applied as inline styles (CSS variable references) to override AdaptiveBox's default 100% sizing
- Precedence: User
classNameandstyleprops take precedence over size classes/styles
Adaptive Sizing
When adaptiveSize={true}, components fill their container and ignore the size prop for layout constraints:
import { Knob } from "@cutoff/audio-ui-react";
export default function AdaptiveSizingExample() {
return (
<div
style={{
display: "grid",
gridTemplateColumns: "1fr 1fr",
gap: "20px",
height: "200px",
}}
>
<Knob
value={0.5}
onChange={(e) => {}}
label="Adaptive"
adaptiveSize={true}
/>
<Knob
value={0.5}
onChange={(e) => {}}
label="Adaptive"
adaptiveSize={true}
/>
</div>
);
}How Adaptive Sizing Works
- No size class or inline size styles are applied
- AdaptiveBox's default
width: 100%; height: 100%takes effect - Component fills its container while maintaining aspect ratio
Size Props
All controls support a size prop and an adaptiveSize prop:
type SizeType = "xsmall" | "small" | "normal" | "large" | "xlarge";
type AdaptiveSizeProps = {
size?: SizeType; // default: "normal"
adaptiveSize?: boolean; // default: false
};Customization
Changing Base Unit
Scale the entire size system by modifying the base unit:
:root {
--audioui-unit: 60px; /* Increase from 48px to 60px */
}All components will scale proportionally while maintaining their aspect ratios:
xsmall: 60px (was 48px)small: 75px (was 60px)normal: 90px (was 72px)large: 120px (was 96px)xlarge: 150px (was 120px)
Overriding Size
Users can override size constraints using className or style props. User-provided styles are spread after size styles, so they take precedence:
import { Knob } from "@cutoff/audio-ui-react";
export default function SizeOverrideExample() {
return (
<div style={{ display: "flex", gap: "20px" }}>
{/* CSS class override (if higher specificity) */}
<Knob
value={0.5}
onChange={(e) => {}}
label="CSS Override"
size="normal"
className="w-20 h-20"
/>
{/* Inline style override (always wins) */}
<Knob
value={0.5}
onChange={(e) => {}}
label="Inline Override"
size="normal"
style={{ width: "100px", height: "100px" }}
/>
</div>
);
}Design System Consistency
The size system ensures mathematical harmony between components:
- A "small" knob (1x1) aligns perfectly with a "small" slider's track width
- All components use the same base unit and multipliers
- Size variations are consistent across component types
- Aspect ratios are preserved at all sizes
Performance Considerations
- CSS Variables: Size classes use CSS variables (computed at render time, cached by browser)
- No JavaScript Calculations: All sizing is CSS-based
- Optimized Merging: Simple object spread for style merging (no
useMemooverhead needed) - Memoization: All controls are wrapped with
React.memo- style objects are only created when props change
Scope: Default Components Only
This sizing system applies exclusively to AudioUI's default components:
- Knob - All variants (abstract, simplest, plainCap, iconCap)
- Slider - All variants (abstract, trackless, trackfull, stripless)
- Button - All variants
- CycleButton - All variants
- Keys - All key styles
Custom components built with Control Primitives and custom view components do not use this sizing system. They implement their own sizing independently.
Integration with AdaptiveBox
The size system works in conjunction with AdaptiveBox:
- Fixed Sizing: Size dimensions override AdaptiveBox's default 100% sizing
- Adaptive Sizing: AdaptiveBox's container-filling behavior takes effect
- Aspect Ratios: Both systems respect component aspect ratios
Next Steps
- Learn about Default Components Styling for theming default components
- Explore AdaptiveBox for layout and responsive behavior
- Check out Control Primitives for building custom components with independent sizing
- See component-specific documentation for size-related features