Skip to content

Commit

Permalink
Initial commit:
Browse files Browse the repository at this point in the history
- Adds default minimum font size limits so that text does not become smaller than 14px/0.875rem/0.875em. The consequence will be that all fluid font sizes will be no smaller than 14px/0.875rem/0.875em in any viewport width.
- Users may define font-sizes that are smaller than 14px/0.875rem/0.875em. In this case the user-defined font size becomes the minimum. For example if a user defines 9px for a block, then the minimum font size for that block will be 9px.
  • Loading branch information
ramonjd committed Oct 15, 2022
1 parent 735f838 commit 3c2a4a1
Show file tree
Hide file tree
Showing 4 changed files with 254 additions and 55 deletions.
95 changes: 65 additions & 30 deletions lib/block-supports/typography.php
Original file line number Diff line number Diff line change
Expand Up @@ -342,11 +342,11 @@ function gutenberg_get_typography_value_and_unit( $raw_value, $options = array()
* @param array $args {
* Optional. An associative array of values to calculate a fluid formula for font size. Default is empty array.
*
* @type string $maximum_viewport_width Maximum size up to which type will have fluidity.
* @type string $minimum_viewport_width Minimum viewport size from which type will have fluidity.
* @type string $maximum_font_size Maximum font size for any clamp() calculation.
* @type string $minimum_font_size Minimum font size for any clamp() calculation.
* @type int $scale_factor A scale factor to determine how fast a font scales within boundaries.
* @type string $maximum_viewport_width Maximum size up to which type will have fluidity.
* @type string $minimum_viewport_width Minimum viewport size from which type will have fluidity.
* @type string $maximum_font_size Maximum font size for any clamp() calculation.
* @type string $minimum_font_size Minimum font size for any clamp() calculation.
* @type int $scale_factor A scale factor to determine how fast a font scales within boundaries.
* }
* @return string|null A font-size value using clamp().
*/
Expand All @@ -357,11 +357,13 @@ function gutenberg_get_computed_fluid_typography_value( $args = array() ) {
$minimum_font_size_raw = isset( $args['minimum_font_size'] ) ? $args['minimum_font_size'] : null;
$scale_factor = isset( $args['scale_factor'] ) ? $args['scale_factor'] : null;

// Grab the minimum font size and normalize it in order to use the value for calculations.
// Grabs the minimum font size and normalize it in order to use the value for calculations.
$minimum_font_size = gutenberg_get_typography_value_and_unit( $minimum_font_size_raw );

// We get a 'preferred' unit to keep units consistent when calculating,
// otherwise the result will not be accurate.
/*
* We get a 'preferred' unit to keep units consistent when calculating,
* otherwise the result will not be accurate.
*/
$font_size_unit = isset( $minimum_font_size['unit'] ) ? $minimum_font_size['unit'] : 'rem';

// Grab the maximum font size and normalize it in order to use the value for calculations.
Expand All @@ -372,12 +374,12 @@ function gutenberg_get_computed_fluid_typography_value( $args = array() ) {
)
);

// Protect against unsupported units.
// Protects against unsupported units.
if ( ! $maximum_font_size || ! $minimum_font_size ) {
return null;
}

// Use rem for accessible fluid target font scaling.
// Uses rem for accessible fluid target font scaling.
$minimum_font_size_rem = gutenberg_get_typography_value_and_unit(
$minimum_font_size_raw,
array(
Expand Down Expand Up @@ -413,36 +415,36 @@ function gutenberg_get_computed_fluid_typography_value( $args = array() ) {
* Returns a font-size value based on a given font-size preset.
* Takes into account fluid typography parameters and attempts to return a css formula depending on available, valid values.
*
* @param array $preset {
* Required. fontSizes preset value as seen in theme.json.
* @param array $font_size {
* Required. fontSizes represented in the preset format as seen in theme.json.
*
* @type string $name Name of the font size preset.
* @type string $slug Kebab-case unique identifier for the font size preset.
* @type string|int|float $size CSS font-size value, including units where applicable.
* }
* @param bool $should_use_fluid_typography An override to switch fluid typography "on". Can be used for unit testing. Default is `false`.
*
* @return string|null Font-size value or `null` if a size is not passed in $preset.
* @return string|null Font-size value or `null` if a size is not passed in $font_size.
*/
function gutenberg_get_typography_font_size_value( $preset, $should_use_fluid_typography = false ) {
if ( ! isset( $preset['size'] ) ) {
function gutenberg_get_typography_font_size_value( $font_size, $should_use_fluid_typography = false ) {
if ( ! isset( $font_size['size'] ) ) {
return null;
}

/*
* Catches empty values and 0/'0'.
* Fluid calculations cannot be performed on 0.
*/
if ( empty( $preset['size'] ) ) {
return $preset['size'];
if ( empty( $font_size['size'] ) ) {
return $font_size['size'];
}

// Check if fluid font sizes are activated.
$typography_settings = gutenberg_get_global_settings( array( 'typography' ) );
$should_use_fluid_typography = isset( $typography_settings['fluid'] ) && true === $typography_settings['fluid'] ? true : $should_use_fluid_typography;

if ( ! $should_use_fluid_typography ) {
return $preset['size'];
return $font_size['size'];
}

// Defaults.
Expand All @@ -451,51 +453,84 @@ function gutenberg_get_typography_font_size_value( $preset, $should_use_fluid_ty
$default_minimum_font_size_factor = 0.75;
$default_maximum_font_size_factor = 1.5;
$default_scale_factor = 1;
$default_minimum_font_size_limit = '14px';

// Font sizes.
$fluid_font_size_settings = isset( $preset['fluid'] ) ? $preset['fluid'] : null;
$fluid_font_size_settings = isset( $font_size['fluid'] ) ? $font_size['fluid'] : null;

// A font size has explicitly bypassed fluid calculations.
if ( false === $fluid_font_size_settings ) {
return $preset['size'];
return $font_size['size'];
}

// Try to grab explicit min and max fluid font sizes.
$minimum_font_size_raw = isset( $fluid_font_size_settings['min'] ) ? $fluid_font_size_settings['min'] : null;
$maximum_font_size_raw = isset( $fluid_font_size_settings['max'] ) ? $fluid_font_size_settings['max'] : null;

// Font sizes.
$preferred_size = gutenberg_get_typography_value_and_unit( $preset['size'] );
// Parses default font size.
$preferred_size = gutenberg_get_typography_value_and_unit( $font_size['size'] );

// Protect against unsupported units.
if ( empty( $preferred_size['unit'] ) ) {
return $preset['size'];
return $font_size['size'];
}

// If no fluid min or max font sizes are available, create some using min/max font size factors.
// If no fluid min font size is available, create one using min font size factor.
if ( ! $minimum_font_size_raw ) {
$minimum_font_size_raw = ( $preferred_size['value'] * $default_minimum_font_size_factor ) . $preferred_size['unit'];
}

// Parses the minimum font size limit, so we can perform checks using it.
$minimum_font_size_limit = gutenberg_get_typography_value_and_unit(
$default_minimum_font_size_limit,
array(
'coerce_to' => $preferred_size['unit'],
)
);

/*
* Checks if a user-defined font size is lower than $minimum_font_size_limit. If so than it should become the minimum font size.
* Otherwise, if the minimum font size is lower than $minimum_font_size_limit
* use $minimum_font_size_limit instead.
*/
if ( ! empty( $minimum_font_size_limit ) ) {
if ( $preferred_size['value'] < $minimum_font_size_limit['value'] ) {
$minimum_font_size_raw = implode( '', $preferred_size );
} else {
$minimum_font_size_parsed = gutenberg_get_typography_value_and_unit(
$minimum_font_size_raw,
array(
'coerce_to' => $preferred_size['unit'],
)
);

if ( ! empty( $minimum_font_size_parsed ) && $minimum_font_size_parsed['value'] < $minimum_font_size_limit['value'] ) {
$minimum_font_size_raw = implode( '', $minimum_font_size_limit );
}
}
}

// If no fluid max font size is available, create one using max font size factor.
if ( ! $maximum_font_size_raw ) {
$maximum_font_size_raw = ( $preferred_size['value'] * $default_maximum_font_size_factor ) . $preferred_size['unit'];
}

$fluid_font_size_value = gutenberg_get_computed_fluid_typography_value(
array(
'minimum_viewport_width' => $default_minimum_viewport_width,
'maximum_viewport_width' => $default_maximum_viewport_width,
'minimum_font_size' => $minimum_font_size_raw,
'maximum_font_size' => $maximum_font_size_raw,
'scale_factor' => $default_scale_factor,
'minimum_viewport_width' => $default_minimum_viewport_width,
'maximum_viewport_width' => $default_maximum_viewport_width,
'minimum_font_size' => $minimum_font_size_raw,
'maximum_font_size' => $maximum_font_size_raw,
'scale_factor' => $default_scale_factor,
'minimum_font_size_limit' => $default_minimum_font_size_limit,
)
);

if ( ! empty( $fluid_font_size_value ) ) {
return $fluid_font_size_value;
}

return $preset['size'];
return $font_size['size'];
}

// Register the block support.
Expand Down
37 changes: 36 additions & 1 deletion packages/block-editor/src/components/font-sizes/fluid-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const DEFAULT_MINIMUM_VIEWPORT_WIDTH = '768px';
const DEFAULT_SCALE_FACTOR = 1;
const DEFAULT_MINIMUM_FONT_SIZE_FACTOR = 0.75;
const DEFAULT_MAXIMUM_FONT_SIZE_FACTOR = 1.5;
const DEFAULT_MINIMUM_FONT_SIZE_LIMIT = '14px';

/**
* Computes a fluid font-size value that uses clamp(). A minimum and maxinmum
Expand Down Expand Up @@ -53,11 +54,12 @@ export function getComputedFluidTypographyValue( {
scaleFactor = DEFAULT_SCALE_FACTOR,
minimumFontSizeFactor = DEFAULT_MINIMUM_FONT_SIZE_FACTOR,
maximumFontSizeFactor = DEFAULT_MAXIMUM_FONT_SIZE_FACTOR,
minimumFontSizeLimit = DEFAULT_MINIMUM_FONT_SIZE_LIMIT,
} ) {
// Calculate missing minimumFontSize and maximumFontSize from
// defaultFontSize if provided.
if ( fontSize && ( ! minimumFontSize || ! maximumFontSize ) ) {
// Parse default font size.
// Parses default font size.
const fontSizeParsed = getTypographyValueAndUnit( fontSize );

// Protect against invalid units.
Expand All @@ -72,6 +74,39 @@ export function getComputedFluidTypographyValue( {
fontSizeParsed.unit;
}

// Parses the minimum font size limit, so we can perform checks using it.
const minimumFontSizeLimitParsed = getTypographyValueAndUnit(
minimumFontSizeLimit,
{
coerceTo: fontSizeParsed.unit,
}
);

/*
* Checks if a user-defined font size is lower than $minimum_font_size_limit. If so than it should become the minimum font size.
* Otherwise, if the minimum font size is lower than $minimum_font_size_limit
* use $minimum_font_size_limit instead.
*/
if ( !! minimumFontSizeLimitParsed?.value ) {
if ( fontSizeParsed.value < minimumFontSizeLimitParsed.value ) {
minimumFontSize = `${ fontSizeParsed.value }${ fontSizeParsed.unit }`;
} else {
const minimumFontSizeParsed = getTypographyValueAndUnit(
minimumFontSize,
{
coerceTo: fontSizeParsed.unit,
}
);
if (
!! minimumFontSizeParsed?.value &&
minimumFontSizeParsed.value <
minimumFontSizeLimitParsed.value
) {
minimumFontSize = `${ minimumFontSizeLimitParsed.value }${ minimumFontSizeLimitParsed.unit }`;
}
}
}

// If no maximumFontSize is provided, derive using max scale factor.
if ( ! maximumFontSize ) {
maximumFontSize =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,77 @@ describe( 'typography utils', () => {
expected:
'clamp(21px, 1.3125rem + ((1vw - 7.68px) * 7.091), 80px)',
},

// Should adjust computed min in px to min limit.
{
preset: {
size: '14px',
},
typographySettings: {
fluid: true,
},
expected:
'clamp(14px, 0.875rem + ((1vw - 7.68px) * 0.841), 21px)',
},

// Should adjust computed min in rem to min limit.
{
preset: {
size: '1.1rem',
},
typographySettings: {
fluid: true,
},
// @TODO round all values to 3 decimal places.
expected:
'clamp(0.875rem, 0.875rem + ((1vw - 0.48rem) * 1.49), 1.65rem)',
},

// Should adjust fluid min value in px to min limit.
{
preset: {
size: '20px',
fluid: {
min: '12px',
},
},
typographySettings: {
fluid: true,
},
expected:
'clamp(14px, 0.875rem + ((1vw - 7.68px) * 1.923), 30px)',
},

// Should adjust fluid min value in rem to min limit.
{
preset: {
size: '1.5rem',
fluid: {
min: '0.5rem',
},
},
typographySettings: {
fluid: true,
},
expected:
'clamp(0.875rem, 0.875rem + ((1vw - 0.48rem) * 2.644), 2.25rem)',
},

// Should adjust fluid min value but honor max value.
{
preset: {
size: '1.5rem',
fluid: {
min: '0.5rem',
max: '5rem',
},
},
typographySettings: {
fluid: true,
},
expected:
'clamp(0.875rem, 0.875rem + ((1vw - 0.48rem) * 7.933), 5rem)',
},
].forEach( ( { preset, typographySettings, expected } ) => {
expect(
getTypographyFontSizeValue( preset, typographySettings )
Expand Down
Loading

0 comments on commit 3c2a4a1

Please sign in to comment.