Skip to content

Commit

Permalink
Editor: Add font size constraints for fluid typography.
Browse files Browse the repository at this point in the history
This commit:
* Adds default minimum font size limits so that min font size, where provided, does not become smaller than `14px`/`0.875rem`/`0.875em`.
* For font sizes of `< 14px` that have no defined minimum sizes, uses the font size to set the floor of the `clamp()` value.

This bugfix prevents converting existing small font sizes to clamp values that will reduce their font size even further in narrow widths. It therefore improves backward compatibility and accessibility.

Original PR from Gutenberg repository:
* [WordPress/gutenberg#44993 #44993 Fluid typography: add font size constraints]

Follow-up to [54260], [54360], [54497], [54500].

Props ramonopoly, andrewserong, isabel_brison, Joen, bernhard-reiter.
Reviewed by bernhard-reiter, SergeyBiryukov.
Merges [54646] to the 6.1 branch.
See #56467.

git-svn-id: https://develop.svn.wordpress.org/branches/6.1@54647 602fd350-edb4-49c9-b593-d223f7449a82
  • Loading branch information
SergeyBiryukov committed Oct 19, 2022
1 parent 8ae6535 commit bfcf5a3
Show file tree
Hide file tree
Showing 2 changed files with 171 additions and 32 deletions.
83 changes: 66 additions & 17 deletions src/wp-includes/block-supports/typography.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,11 @@ function wp_apply_typography_support( $block_type, $block_attributes ) {
$custom_font_size = isset( $block_attributes['style']['typography']['fontSize'] )
? $block_attributes['style']['typography']['fontSize']
: null;
$typography_block_styles['fontSize'] = $preset_font_size ? $preset_font_size : wp_get_typography_font_size_value(
array(
'size' => $custom_font_size,
)
);
$typography_block_styles['fontSize'] = $preset_font_size ? $preset_font_size : wp_get_typography_font_size_value(
array(
'size' => $custom_font_size,
)
);
}

if ( $has_font_family_support && ! $should_skip_font_family ) {
Expand Down Expand Up @@ -348,8 +348,17 @@ function wp_get_typography_value_and_unit( $raw_value, $options = array() ) {
$unit = $options['coerce_to'];
}

/*
* No calculation is required if swapping between em and rem yet,
* since we assume a root size value. Later we might like to differentiate between
* :root font size (rem) and parent element font size (em) relativity.
*/
if ( ( 'em' === $options['coerce_to'] || 'rem' === $options['coerce_to'] ) && ( 'em' === $unit || 'rem' === $unit ) ) {
$unit = $options['coerce_to'];
}

return array(
'value' => $value,
'value' => round( $value, 3 ),
'unit' => $unit,
);
}
Expand Down Expand Up @@ -380,26 +389,29 @@ function wp_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.
// Normalizes the minimum font size in order to use the value for calculations.
$minimum_font_size = wp_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.
// Normalizes the maximum font size in order to use the value for calculations.
$maximum_font_size = wp_get_typography_value_and_unit(
$maximum_font_size_raw,
array(
'coerce_to' => $font_size_unit,
)
);

// Protect against unsupported units.
// Checks for mandatory min and max sizes, and 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 = wp_get_typography_value_and_unit(
$minimum_font_size_raw,
array(
Expand Down Expand Up @@ -427,8 +439,9 @@ function wp_get_computed_fluid_typography_value( $args = array() ) {
*/
$view_port_width_offset = round( $minimum_viewport_width['value'] / 100, 3 ) . $font_size_unit;
$linear_factor = 100 * ( ( $maximum_font_size['value'] - $minimum_font_size['value'] ) / ( $maximum_viewport_width['value'] - $minimum_viewport_width['value'] ) );
$linear_factor = round( $linear_factor, 3 ) * $scale_factor;
$fluid_target_font_size = implode( '', $minimum_font_size_rem ) . " + ((1vw - $view_port_width_offset) * $linear_factor)";
$linear_factor_scaled = round( $linear_factor * $scale_factor, 3 );
$linear_factor_scaled = empty( $linear_factor_scaled ) ? 1 : $linear_factor_scaled;
$fluid_target_font_size = implode( '', $minimum_font_size_rem ) . " + ((1vw - $view_port_width_offset) * $linear_factor_scaled)";

return "clamp($minimum_font_size_raw, $fluid_target_font_size, $maximum_font_size_raw)";
}
Expand Down Expand Up @@ -478,6 +491,7 @@ function wp_get_typography_font_size_value( $preset, $should_use_fluid_typograph
$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;
Expand All @@ -499,13 +513,48 @@ function wp_get_typography_font_size_value( $preset, $should_use_fluid_typograph
return $preset['size'];
}

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

// 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'];
$minimum_font_size_raw = round( $preferred_size['value'] * $default_minimum_font_size_factor, 3 ) . $preferred_size['unit'];
}

if ( ! $maximum_font_size_raw ) {
$maximum_font_size_raw = ( $preferred_size['value'] * $default_maximum_font_size_factor ) . $preferred_size['unit'];
// Normalizes the minimum font size limit according to the incoming unit, so we can perform checks using it.
$minimum_font_size_limit = wp_get_typography_value_and_unit(
$default_minimum_font_size_limit,
array(
'coerce_to' => $preferred_size['unit'],
)
);

if ( ! empty( $minimum_font_size_limit ) ) {
/*
* If a minimum size was not passed to this function
* and the user-defined font size is lower than $minimum_font_size_limit,
* then use the user-defined font size as the minimum font-size.
*/
if ( ! isset( $fluid_font_size_settings['min'] ) && $preferred_size['value'] < $minimum_font_size_limit['value'] ) {
$minimum_font_size_raw = implode( '', $preferred_size );
} else {
$minimum_font_size_parsed = wp_get_typography_value_and_unit(
$minimum_font_size_raw,
array(
'coerce_to' => $preferred_size['unit'],
)
);

/*
* If the passed or calculated minimum font size is lower than $minimum_font_size_limit
* use $minimum_font_size_limit instead.
*/
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 );
}
}
}

$fluid_font_size_value = wp_get_computed_fluid_typography_value(
Expand Down
120 changes: 105 additions & 15 deletions tests/phpunit/tests/block-supports/typography.php
Original file line number Diff line number Diff line change
Expand Up @@ -363,11 +363,11 @@ public function data_generate_font_size_preset_fixtures() {

'default_return_value_when_value_is_already_clamped' => array(
'font_size_preset' => array(
'size' => 'clamp(21px, 1.3125rem + ((1vw - 7.68px) * 2.524), 42px)',
'size' => 'clamp(21px, 1.313rem + ((1vw - 7.68px) * 2.524), 42px)',
'fluid' => false,
),
'should_use_fluid_typography' => true,
'expected_output' => 'clamp(21px, 1.3125rem + ((1vw - 7.68px) * 2.524), 42px)',
'expected_output' => 'clamp(21px, 1.313rem + ((1vw - 7.68px) * 2.524), 42px)',
),

'default_return_value_with_unsupported_unit' => array(
Expand All @@ -384,31 +384,31 @@ public function data_generate_font_size_preset_fixtures() {
'size' => '1.75rem',
),
'should_use_fluid_typography' => true,
'expected_output' => 'clamp(1.3125rem, 1.3125rem + ((1vw - 0.48rem) * 2.524), 2.625rem)',
'expected_output' => 'clamp(1.313rem, 1.313rem + ((1vw - 0.48rem) * 2.523), 2.625rem)',
),

'return_fluid_value_with_floats_with_units' => array(
'font_size_preset' => array(
'size' => '100.175px',
),
'should_use_fluid_typography' => true,
'expected_output' => 'clamp(75.13125px, 4.695703125rem + ((1vw - 7.68px) * 9.03), 150.2625px)',
'expected_output' => 'clamp(75.131px, 4.696rem + ((1vw - 7.68px) * 9.03), 150.263px)',
),

'return_fluid_value_with_integer_coerced_to_px' => array(
'font_size_preset' => array(
'size' => 33,
),
'should_use_fluid_typography' => true,
'expected_output' => 'clamp(24.75px, 1.546875rem + ((1vw - 7.68px) * 2.975), 49.5px)',
'expected_output' => 'clamp(24.75px, 1.547rem + ((1vw - 7.68px) * 2.975), 49.5px)',
),

'return_fluid_value_with_float_coerced_to_px' => array(
'font_size_preset' => array(
'size' => 100.23,
),
'should_use_fluid_typography' => true,
'expected_output' => 'clamp(75.1725px, 4.69828125rem + ((1vw - 7.68px) * 9.035), 150.345px)',
'expected_output' => 'clamp(75.173px, 4.698rem + ((1vw - 7.68px) * 9.035), 150.345px)',
),

'return_default_fluid_values_with_empty_fluid_array' => array(
Expand All @@ -417,7 +417,7 @@ public function data_generate_font_size_preset_fixtures() {
'fluid' => array(),
),
'should_use_fluid_typography' => true,
'expected_output' => 'clamp(21px, 1.3125rem + ((1vw - 7.68px) * 2.524), 42px)',
'expected_output' => 'clamp(21px, 1.313rem + ((1vw - 7.68px) * 2.524), 42px)',
),

'return_default_fluid_values_with_null_value' => array(
Expand All @@ -426,7 +426,19 @@ public function data_generate_font_size_preset_fixtures() {
'fluid' => null,
),
'should_use_fluid_typography' => true,
'expected_output' => 'clamp(21px, 1.3125rem + ((1vw - 7.68px) * 2.524), 42px)',
'expected_output' => 'clamp(21px, 1.313rem + ((1vw - 7.68px) * 2.524), 42px)',
),

'return_clamped_value_if_min_font_size_is_greater_than_max' => array(
'font_size_preset' => array(
'size' => '3rem',
'fluid' => array(
'min' => '5rem',
'max' => '32px',
),
),
'should_use_fluid_typography' => true,
'expected_output' => 'clamp(5rem, 5rem + ((1vw - 0.48rem) * -5.769), 32px)',
),

'return_size_with_invalid_fluid_units' => array(
Expand All @@ -441,7 +453,15 @@ public function data_generate_font_size_preset_fixtures() {
'expected_output' => '10em',
),

'return_fluid_clamp_value' => array(
'return_clamped_size_where_no_min_is_given_and_less_than_default_min_size' => array(
'font_size_preset' => array(
'size' => '3px',
),
'should_use_fluid_typography' => true,
'expected_output' => 'clamp(3px, 0.188rem + ((1vw - 7.68px) * 0.18), 4.5px)',
),

'return_fluid_clamp_value_with_different_min_max_units' => array(
'font_size_preset' => array(
'size' => '28px',
'fluid' => array(
Expand Down Expand Up @@ -472,7 +492,77 @@ public function data_generate_font_size_preset_fixtures() {
),
),
'should_use_fluid_typography' => true,
'expected_output' => 'clamp(21px, 1.3125rem + ((1vw - 7.68px) * 7.091), 80px)',
'expected_output' => 'clamp(21px, 1.313rem + ((1vw - 7.68px) * 7.091), 80px)',
),

'should_adjust_computed_min_in_px_to_min_limit' => array(
'font_size_preset' => array(
'size' => '14px',
),
'should_use_fluid_typography' => true,
'expected_output' => 'clamp(14px, 0.875rem + ((1vw - 7.68px) * 0.841), 21px)',
),

'should_adjust_computed_min_in_rem_to_min_limit' => array(
'font_size_preset' => array(
'size' => '1.1rem',
),
'should_use_fluid_typography' => true,
'expected_output' => 'clamp(0.875rem, 0.875rem + ((1vw - 0.48rem) * 1.49), 1.65rem)',
),

'default_return_clamp_value_with_replaced_fluid_min_value_in_em' => array(
'font_size_preset' => array(
'size' => '1.1em',
),
'should_use_fluid_typography' => true,
'expected_output' => 'clamp(0.875em, 0.875rem + ((1vw - 0.48em) * 1.49), 1.65em)',
),

'should_adjust_fluid_min_value_in_px_to_min_limit' => array(
'font_size_preset' => array(
'size' => '20px',
'fluid' => array(
'min' => '12px',
),
),
'should_use_fluid_typography' => true,
'expected_output' => 'clamp(14px, 0.875rem + ((1vw - 7.68px) * 1.923), 30px)',
),

'should_adjust_fluid_min_value_in_rem_to_min_limit' => array(
'font_size_preset' => array(
'size' => '1.5rem',
'fluid' => array(
'min' => '0.5rem',
),
),
'should_use_fluid_typography' => true,
'expected_output' => 'clamp(0.875rem, 0.875rem + ((1vw - 0.48rem) * 2.644), 2.25rem)',
),

'should_adjust_fluid_min_value_but_honor_max_value' => array(
'font_size_preset' => array(
'size' => '1.5rem',
'fluid' => array(
'min' => '0.5rem',
'max' => '5rem',
),
),
'should_use_fluid_typography' => true,
'expected_output' => 'clamp(0.875rem, 0.875rem + ((1vw - 0.48rem) * 7.933), 5rem)',
),

'should_return_fluid_value_when_min_and_max_font_sizes_are_equal' => array(
'font_size_preset' => array(
'size' => '4rem',
'fluid' => array(
'min' => '30px',
'max' => '30px',
),
),
'should_use_fluid_typography' => true,
'expected_output' => 'clamp(30px, 1.875rem + ((1vw - 7.68px) * 1), 30px)',
),
);
}
Expand Down Expand Up @@ -547,7 +637,7 @@ public function data_generate_block_supports_font_size_fixtures() {
'return_value_with_fluid_typography' => array(
'font_size_value' => '50px',
'should_use_fluid_typography' => true,
'expected_output' => 'font-size:clamp(37.5px, 2.34375rem + ((1vw - 7.68px) * 4.507), 75px);',
'expected_output' => 'font-size:clamp(37.5px, 2.344rem + ((1vw - 7.68px) * 4.507), 75px);',
),
);
}
Expand Down Expand Up @@ -623,13 +713,13 @@ public function data_generate_replace_inline_font_styles_with_fluid_values_fixtu
'block_content' => '<p class="has-medium-font-size" style=" font-size: 20px ; ">A paragraph inside a group</p>',
'font_size_value' => '20px',
'should_use_fluid_typography' => true,
'expected_output' => '<p class="has-medium-font-size" style=" font-size:clamp(15px, 0.9375rem + ((1vw - 7.68px) * 1.803), 30px); ">A paragraph inside a group</p>',
'expected_output' => '<p class="has-medium-font-size" style=" font-size:clamp(15px, 0.938rem + ((1vw - 7.68px) * 1.803), 30px); ">A paragraph inside a group</p>',
),
'return_content_with_first_match_replace_only' => array(
'block_content' => "<div class=\"wp-block-group\" style=\"font-size:1em\"> \n \n<p style=\"font-size:1em\">A paragraph inside a group</p></div>",
'font_size_value' => '1em',
'block_content' => "<div class=\"wp-block-group\" style=\"font-size:1.5em\"> \n \n<p style=\"font-size:1.5em\">A paragraph inside a group</p></div>",
'font_size_value' => '1.5em',
'should_use_fluid_typography' => true,
'expected_output' => "<div class=\"wp-block-group\" style=\"font-size:clamp(0.75em, 0.75em + ((1vw - 0.48em) * 1.442), 1.5em);\"> \n \n<p style=\"font-size:1em\">A paragraph inside a group</p></div>",
'expected_output' => "<div class=\"wp-block-group\" style=\"font-size:clamp(1.125em, 1.125rem + ((1vw - 0.48em) * 2.163), 2.25em);\"> \n \n<p style=\"font-size:1.5em\">A paragraph inside a group</p></div>",
),
);
}
Expand Down

0 comments on commit bfcf5a3

Please sign in to comment.