-
-
Save doiftrue/67b6f488e16ea989be5175678c69536d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * Generates ready-to-use CSS variables with fluid values via `clamp()`, so that sizes in `rem` | |
| * smoothly change between two viewport widths and do not exceed specified minimums and maximums. | |
| * | |
| * Usage example: | |
| * | |
| * $formatter = new Fluid_CSSVar_Generator( | |
| * 375, // minimum viewport width in pixels | |
| * 1280, // maximum viewport width in pixels | |
| * 150, // scaling factor in percent | |
| * 0 // minimum size in pixels | |
| * ); | |
| * echo $formatter->generate( [12, 48], 4 ); | |
| * // or get single variable: | |
| * echo $formatter->get_css_var( 24 ); | |
| * | |
| * @ver 1.0.1 | |
| */ | |
| class Fluid_CSSVar_Generator { | |
| public int $root_size_px = 16; | |
| public string $var_pattern = '--fluid{scale}-{px}px'; | |
| /** | |
| * @param int $vw_min_width The minimum viewport width in pixels. | |
| * @param int $vw_max_width The maximum viewport width in pixels. | |
| * @param float $scale_percent The scaling factor between minimum and maximum size. | |
| * @param int $min_size_px The minimum size in pixels. Less than this size will not be used. | |
| */ | |
| public function __construct( | |
| private readonly int $vw_min_width = 375, | |
| private readonly int $vw_max_width = 1280, | |
| private readonly int $scale_percent = 150, | |
| private readonly int $min_size_px = 0, | |
| ){ | |
| ( $this->scale_percent <= 100 ) && throw new InvalidArgumentException( '$scale_percent must be greater than 1.' ); | |
| ( $this->min_size_px < 0 ) && throw new InvalidArgumentException( '$min_size_px cannot be negative.' ); | |
| } | |
| /** | |
| * @param array $px_range Minimum and maximum size in pixels at the maximum viewport width. | |
| * @param int $step The step between sizes in pixels. | |
| */ | |
| public function generate( array $px_range, int $step = 1 ): string { | |
| $result = []; | |
| for ( $px = $px_range[0]; $px <= $px_range[1]; $px += $step ) { | |
| $result[] = $this->get_css_var( $px ); | |
| } | |
| return implode( "\n", $result ); | |
| } | |
| /** | |
| * @param int $px The maximum size in pixels at the maximum viewport width. | |
| */ | |
| public function get_css_var( int $px ): string { | |
| $vw_min_rem = ( $this->vw_min_width / 100 ) / $this->root_size_px; | |
| $vw_max_rem = ( $this->vw_max_width / 100 ) / $this->root_size_px; | |
| $vw_range = $vw_max_rem - $vw_min_rem; | |
| $scale_factor = $this->scale_percent / 100; | |
| $font_max_rem = $px / $this->root_size_px; | |
| $font_min_rem = max( $font_max_rem / $scale_factor, $this->min_size_px / $this->root_size_px ); | |
| if ( $font_max_rem <= $font_min_rem ) { | |
| $min = self::format_value( $font_min_rem ); | |
| return strtr( | |
| $this->var_pattern . ': {min}rem;', | |
| [ | |
| '{scale}' => $this->scale_percent, | |
| '{px}' => $px, | |
| '{min}' => $min, | |
| ] | |
| ); | |
| } | |
| $font_range = $font_max_rem - $font_min_rem; | |
| $slope = $font_range / $vw_range; | |
| $intercept = $font_min_rem - ( $slope * $vw_min_rem ); | |
| return strtr( | |
| $this->var_pattern . ': clamp({min}rem, {intercept}rem + {slope}vw, {max}rem);', | |
| [ | |
| '{scale}' => $this->scale_percent, | |
| '{px}' => $px, | |
| '{min}' => self::format_value( $font_min_rem ), | |
| '{intercept}' => self::format_value( $intercept ), | |
| '{slope}' => self::format_value( $slope ), | |
| '{max}' => self::format_value( $font_max_rem ), | |
| ] | |
| ); | |
| } | |
| private static function format_value( float $value ): string { | |
| return number_format( $value, 3, '.', '' ); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment