Skip to content

Commit

Permalink
Allow using CSS level 4 viewport-relative units (#54415)
Browse files Browse the repository at this point in the history
* Allow using new-ish CSS viewport-relative units

* Fix typo

* Improve svi/svb description
  • Loading branch information
aristath authored Oct 9, 2023
1 parent 0daa67b commit ec8b13c
Show file tree
Hide file tree
Showing 11 changed files with 299 additions and 11 deletions.
52 changes: 50 additions & 2 deletions packages/block-editor/src/components/height-control/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,28 @@ const RANGE_CONTROL_CUSTOM_SETTINGS = {
vh: { max: 100, step: 1 },
em: { max: 50, step: 0.1 },
rem: { max: 50, step: 0.1 },
svw: { max: 100, step: 1 },
lvw: { max: 100, step: 1 },
dvw: { max: 100, step: 1 },
svh: { max: 100, step: 1 },
lvh: { max: 100, step: 1 },
dvh: { max: 100, step: 1 },
vi: { max: 100, step: 1 },
svi: { max: 100, step: 1 },
lvi: { max: 100, step: 1 },
dvi: { max: 100, step: 1 },
vb: { max: 100, step: 1 },
svb: { max: 100, step: 1 },
lvb: { max: 100, step: 1 },
dvb: { max: 100, step: 1 },
vmin: { max: 100, step: 1 },
svmin: { max: 100, step: 1 },
lvmin: { max: 100, step: 1 },
dvmin: { max: 100, step: 1 },
vmax: { max: 100, step: 1 },
svmax: { max: 100, step: 1 },
lvmax: { max: 100, step: 1 },
dvmax: { max: 100, step: 1 },
};

/**
Expand Down Expand Up @@ -86,10 +108,36 @@ export default function HeightControl( {
// Convert to pixel value assuming a root size of 16px.
onChange( Math.round( currentValue * 16 ) + newUnit );
} else if (
[ 'vh', 'vw', '%' ].includes( newUnit ) &&
[
'%',
'vw',
'svw',
'lvw',
'dvw',
'vh',
'svh',
'lvh',
'dvh',
'vi',
'svi',
'lvi',
'dvi',
'vb',
'svb',
'lvb',
'dvb',
'vmin',
'svmin',
'lvmin',
'dvmin',
'vmax',
'svmax',
'lvmax',
'dvmax',
].includes( newUnit ) &&
currentValue > 100
) {
// When converting to `vh`, `vw`, or `%` units, cap the new value at 100.
// When converting to `%` or viewport-relative units, cap the new value at 100.
onChange( 100 + newUnit );
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,28 @@ const CUSTOM_VALUE_SETTINGS = {
vh: { max: 100, steps: 1 },
em: { max: 10, steps: 0.1 },
rm: { max: 10, steps: 0.1 },
svw: { max: 100, steps: 1 },
lvw: { max: 100, steps: 1 },
dvw: { max: 100, steps: 1 },
svh: { max: 100, steps: 1 },
lvh: { max: 100, steps: 1 },
dvh: { max: 100, steps: 1 },
vi: { max: 100, steps: 1 },
svi: { max: 100, steps: 1 },
lvi: { max: 100, steps: 1 },
dvi: { max: 100, steps: 1 },
vb: { max: 100, steps: 1 },
svb: { max: 100, steps: 1 },
lvb: { max: 100, steps: 1 },
dvb: { max: 100, steps: 1 },
vmin: { max: 100, steps: 1 },
svmin: { max: 100, steps: 1 },
lvmin: { max: 100, steps: 1 },
dvmin: { max: 100, steps: 1 },
vmax: { max: 100, steps: 1 },
svmax: { max: 100, steps: 1 },
lvmax: { max: 100, steps: 1 },
dvmax: { max: 100, steps: 1 },
};

export default function SpacingInputControl( {
Expand Down
52 changes: 50 additions & 2 deletions packages/block-editor/src/layouts/grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,28 @@ const RANGE_CONTROL_MAX_VALUES = {
vh: 100,
em: 38,
rem: 38,
svw: 100,
lvw: 100,
dvw: 100,
svh: 100,
lvh: 100,
dvh: 100,
vi: 100,
svi: 100,
lvi: 100,
dvi: 100,
vb: 100,
svb: 100,
lvb: 100,
dvb: 100,
vmin: 100,
svmin: 100,
lvmin: 100,
dvmin: 100,
vmax: 100,
svmax: 100,
lvmax: 100,
dvmax: 100,
};

export default {
Expand Down Expand Up @@ -131,10 +153,36 @@ function GridLayoutMinimumWidthControl( { layout, onChange } ) {
// Convert to pixel value assuming a root size of 16px.
newValue = Math.round( quantity * 16 ) + newUnit;
} else if (
[ 'vh', 'vw', '%' ].includes( newUnit ) &&
[
'vh',
'vw',
'%',
'svw',
'lvw',
'dvw',
'svh',
'lvh',
'dvh',
'vi',
'svi',
'lvi',
'dvi',
'vb',
'svb',
'lvb',
'dvb',
'vmin',
'svmin',
'lvmin',
'dvmin',
'vmax',
'svmax',
'lvmax',
'dvmax',
].includes( newUnit ) &&
quantity > 100
) {
// When converting to `vh`, `vw`, or `%` units, cap the new value at 100.
// When converting to `%` or viewport-relative units, cap the new value at 100.
newValue = 100 + newUnit;
}

Expand Down
3 changes: 2 additions & 1 deletion packages/block-editor/src/layouts/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ export function getBlockGapCSS(
export function getAlignmentsInfo( layout ) {
const { contentSize, wideSize, type = 'default' } = layout;
const alignmentInfo = {};
const sizeRegex = /^(?!0)\d+(px|em|rem|vw|vh|%)?$/i;
const sizeRegex =
/^(?!0)\d+(px|em|rem|vw|vh|%|svw|lvw|dvw|svh|lvh|dvh|vi|svi|lvi|dvi|vb|svb|lvb|dvb|vmin|svmin|lvmin|dvmin|vmax|svmax|lvmax|dvmax)?$/i;
if ( sizeRegex.test( contentSize ) && type === 'constrained' ) {
// translators: %s: container size (i.e. 600px etc)
alignmentInfo.none = sprintf( __( 'Max %s wide' ), contentSize );
Expand Down
20 changes: 20 additions & 0 deletions packages/block-editor/src/utils/parse-css-unit-to-px.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,26 @@ function convertParsedUnitToPx( parsedUnit, options ) {
ex: 7.15625, // X-height of the element's font. Approximate.
lh: setOptions.lineHeight,
};
relativeUnits.svw = relativeUnits.vmin;
relativeUnits.lvw = relativeUnits.vmax;
relativeUnits.dvw = relativeUnits.vw;
relativeUnits.svh = relativeUnits.vmin;
relativeUnits.lvh = relativeUnits.vmax;
relativeUnits.dvh = relativeUnits.vh;
relativeUnits.vi = relativeUnits.vh;
relativeUnits.svi = relativeUnits.vmin;
relativeUnits.lvi = relativeUnits.vmax;
relativeUnits.dvi = relativeUnits.vw;
relativeUnits.vb = relativeUnits.vh;
relativeUnits.svb = relativeUnits.vmin;
relativeUnits.lvb = relativeUnits.vmax;
relativeUnits.dvb = relativeUnits.vh;
relativeUnits.svmin = relativeUnits.vmin;
relativeUnits.lvmin = relativeUnits.vmin;
relativeUnits.dvmin = relativeUnits.vmin;
relativeUnits.svmax = relativeUnits.vmax;
relativeUnits.lvmax = relativeUnits.vmax;
relativeUnits.dvmax = relativeUnits.vmax;

const absoluteUnits = {
in: PIXELS_PER_INCH,
Expand Down
3 changes: 2 additions & 1 deletion packages/components/src/font-size-picker/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import { parseQuantityAndUnitFromRawValue } from '../unit-control';
export function isSimpleCssValue(
value: NonNullable< FontSizePickerProps[ 'value' ] >
) {
const sizeRegex = /^[\d\.]+(px|em|rem|vw|vh|%)?$/i;
const sizeRegex =
/^[\d\.]+(px|em|rem|vw|vh|%|svw|lvw|dvw|svh|lvh|dvh|vi|svi|lvi|dvi|vb|svb|lvb|dvb|vmin|svmin|lvmin|dvmin|vmax|svmax|lvmax|dvmax)?$/i;
return sizeRegex.test( String( value ) );
}

Expand Down
2 changes: 1 addition & 1 deletion packages/components/src/sandbox/index.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ const observeAndResizeJS = `
style
) {
if (
/^\\d+(vmin|vmax|vh|vw)$/.test( ruleOrNode.style[ style ] )
/^\\d+(vw|vh|svw|lvw|dvw|svh|lvh|dvh|vi|svi|lvi|dvi|vb|svb|lvb|dvb|vmin|svmin|lvmin|dvmin|vmax|svmax|lvmax|dvmax)$/.test( ruleOrNode.style[ style ] )
) {
ruleOrNode.style[ style ] = '';
}
Expand Down
4 changes: 3 additions & 1 deletion packages/components/src/sandbox/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ const observeAndResizeJS = function () {
[ 'width', 'height', 'minHeight', 'maxHeight' ] as const
).forEach( function ( style ) {
if (
/^\\d+(vmin|vmax|vh|vw)$/.test( ruleOrNode.style[ style ] )
/^\\d+(vw|vh|svw|lvw|dvw|svh|lvh|dvh|vi|svi|lvi|dvi|vb|svb|lvb|dvb|vmin|svmin|lvmin|dvmin|vmax|svmax|lvmax|dvmax)$/.test(
ruleOrNode.style[ style ]
)
) {
ruleOrNode.style[ style ] = '';
}
Expand Down
124 changes: 124 additions & 0 deletions packages/components/src/unit-control/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,130 @@ const allUnits: Record< string, WPUnitControlUnit > = {
a11yLabel: __( 'Points (pt)' ),
step: 1,
},
svw: {
value: 'svw',
label: isWeb ? 'svw' : __( 'Small viewport width (svw)' ),
a11yLabel: __( 'Small viewport width (svw)' ),
step: 0.1,
},
svh: {
value: 'svh',
label: isWeb ? 'svh' : __( 'Small viewport height (svh)' ),
a11yLabel: __( 'Small viewport height (svh)' ),
step: 0.1,
},
svi: {
value: 'svi',
label: isWeb
? 'svi'
: __( 'Viewport smallest size in the inline direction (svi)' ),
a11yLabel: __( 'Small viewport width or height (svi)' ),
step: 0.1,
},
svb: {
value: 'svb',
label: isWeb
? 'svb'
: __( 'Viewport smallest size in the block direction (svb)' ),
a11yLabel: __( 'Small viewport width or height (svb)' ),
step: 0.1,
},
svmin: {
value: 'svmin',
label: isWeb
? 'svmin'
: __( 'Small viewport smallest dimension (svmin)' ),
a11yLabel: __( 'Small viewport smallest dimension (svmin)' ),
step: 0.1,
},
lvw: {
value: 'lvw',
label: isWeb ? 'lvw' : __( 'Large viewport width (lvw)' ),
a11yLabel: __( 'Large viewport width (lvw)' ),
step: 0.1,
},
lvh: {
value: 'lvh',
label: isWeb ? 'lvh' : __( 'Large viewport height (lvh)' ),
a11yLabel: __( 'Large viewport height (lvh)' ),
step: 0.1,
},
lvi: {
value: 'lvi',
label: isWeb ? 'lvi' : __( 'Large viewport width or height (lvi)' ),
a11yLabel: __( 'Large viewport width or height (lvi)' ),
step: 0.1,
},
lvb: {
value: 'lvb',
label: isWeb ? 'lvb' : __( 'Large viewport width or height (lvb)' ),
a11yLabel: __( 'Large viewport width or height (lvb)' ),
step: 0.1,
},
lvmin: {
value: 'lvmin',
label: isWeb
? 'lvmin'
: __( 'Large viewport smallest dimension (lvmin)' ),
a11yLabel: __( 'Large viewport smallest dimension (lvmin)' ),
step: 0.1,
},
dvw: {
value: 'dvw',
label: isWeb ? 'dvw' : __( 'Dynamic viewport width (dvw)' ),
a11yLabel: __( 'Dynamic viewport width (dvw)' ),
step: 0.1,
},
dvh: {
value: 'dvh',
label: isWeb ? 'dvh' : __( 'Dynamic viewport height (dvh)' ),
a11yLabel: __( 'Dynamic viewport height (dvh)' ),
step: 0.1,
},
dvi: {
value: 'dvi',
label: isWeb ? 'dvi' : __( 'Dynamic viewport width or height (dvi)' ),
a11yLabel: __( 'Dynamic viewport width or height (dvi)' ),
step: 0.1,
},
dvb: {
value: 'dvb',
label: isWeb ? 'dvb' : __( 'Dynamic viewport width or height (dvb)' ),
a11yLabel: __( 'Dynamic viewport width or height (dvb)' ),
step: 0.1,
},
dvmin: {
value: 'dvmin',
label: isWeb
? 'dvmin'
: __( 'Dynamic viewport smallest dimension (dvmin)' ),
a11yLabel: __( 'Dynamic viewport smallest dimension (dvmin)' ),
step: 0.1,
},
dvmax: {
value: 'dvmax',
label: isWeb
? 'dvmax'
: __( 'Dynamic viewport largest dimension (dvmax)' ),
a11yLabel: __( 'Dynamic viewport largest dimension (dvmax)' ),
step: 0.1,
},
svmax: {
value: 'svmax',
label: isWeb
? 'svmax'
: __( 'Small viewport largest dimension (svmax)' ),
a11yLabel: __( 'Small viewport largest dimension (svmax)' ),
step: 0.1,
},
lvmax: {
value: 'lvmax',
label: isWeb
? 'lvmax'
: __( 'Large viewport largest dimension (lvmax)' ),
a11yLabel: __( 'Large viewport largest dimension (lvmax)' ),
step: 0.1,
},
};

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/components/src/utils/unit-values.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const UNITED_VALUE_REGEX =
/^([\d.\-+]*)\s*(fr|cm|mm|Q|in|pc|pt|px|em|ex|ch|rem|lh|vw|vh|vmin|vmax|%|cap|ic|rlh|vi|vb|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?$/;
/^([\d.\-+]*)\s*(fr|cm|mm|Q|in|pc|pt|px|em|ex|ch|rem|lh|vw|vh|vmin|vmax|%|cap|ic|rlh|vi|vb|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx|svw|lvw|dvw|svh|lvh|dvh|svi|lvi|dvi|svb|lvb|dvb|svmin|lvmin|dvmin|svmax|lvmax|dvmax)?$/;

/**
* Parses a number and unit from a value.
Expand Down
Loading

0 comments on commit ec8b13c

Please sign in to comment.