Category: CSS

  • Fluid Scaling: Controlling Bounds with Min and Max

    While the fxx() function ensures perfect proportionality, pure fluid scaling can be dangerous.

    If a paragraph has font-size: fxx(16) (based on a 1920px design), and a user views it on a 320px mobile phone, the font size will proportionally scale down to roughly 2.6px. This is completely illegible.

    Therefore, we must set “guardrails”—mathematical boundaries that dictate how small or how large an element is allowed to scale. We handle this using the CSS native min()max(), and clamp() functions.

    1. Establishing a Floor with max()

    The CSS max(val1, val2) function compares two or more comma-separated values and applies the largest one. We use this to establish a minimum bound (a “floor”).

    The Logic: “Take the fluidly scaled value… UNLESS it falls below a specific pixel amount. If it does, stop scaling and lock it at that pixel amount.”

    Example Scenario: We have an icon that is 48px on desktop. We want it to scale down fluidly, but it shouldn’t get so small it becomes difficult to tap. We decide 30px is the absolute minimum acceptable size.

    .icon {
        /* SCSS */
        width: max(30px, fxx(48));
        height: max(30px, fxx(48));
    }
    • Desktop (1920px): max(30px, 48px) -> Browser chooses 48px.
    • Tablet (960px): The fluid value halves to 24pxmax(30px, 24px) -> The browser chooses 30px. The icon stops shrinking and remains locked at a legible size.

    Crucial Detail: Notice that inside the max() function, the floor value (30px) explicitly requires the unit, while the fxx() argument (48) does not.

    2. Establishing a Ceiling with min()

    Conversely, the CSS min(val1, val2) function applies the smallest value. We use this to establish a maximum bound (a “ceiling”), preventing elements from blowing up to ridiculous proportions on ultra-wide (e.g., 4K) monitors.

    Example Scenario: A content card should be 460px wide. We want it to shrink on small screens, but we never want it to stretch beyond 460px or 100% of its parent container.

    .content-card {
        /* SCSS */
        width: min(fxx(460), 100%);
    }

    (In this case, we use 100% as our ceiling rather than a fixed pixel value, ensuring it never causes horizontal scrollbars).

    3. The Best of Both Worlds: clamp()

    When you need an element to have both a floor (minimum limit) and a ceiling (maximum limit), you can use the CSS clamp() function.

    The syntax is always strictly in this order: clamp(MINIMUM, IDEAL_FLUID_VALUE, MAXIMUM).

    This is incredibly common for typography. For instance, you might want a headline to dynamically scale based on 120px ideally, but you want to guarantee it will never be smaller than 40px on phones, and never larger than 120px on giant TVs.

    The fxx-clamp() SCSS Helper

    To simplify typography scaling, our _functions.scss provides the fxx-clamp() utility:

    /// @param {Number} $max - The upper limit and the scale base (e.g., 180 for `180px`).
    /// @param {Number} $min - The lower limit pixel restriction. Defaults to `40`.
    @function fxx-clamp($max, $min: 40) {
        @return clamp(#{$min}px, calc(#{$max} * var(--wp--custom--fxx)), #{$max}px);
    }

    Usage:

    h1 {
        /* Ideally scales based on 120px, but never falls below 45px, and never exceeds 120px */
        font-size: fxx-clamp(120, 45);
    }

    Summary

    • Use fxx(val) when an element should scale infinitely.
    • Use max(minValpx, fxx(idealVal)) to prevent something from shrinking too much (setting a floor).
    • Use min(maxValpx, fxx(idealVal)) or min(fxx(idealVal), 100%) to prevent something from growing too much (setting a ceiling).
    • Use fxx-clamp(maxVal, minVal) to set strict boundaries on both ends, typically for typography.
  • Fluid Scaling: Implementation in SCSS

    In Part 1, we learned that the core of our fluid scaling relies on wrapping a target pixel value in a calc() function multiplied by our global ratio variable: calc(VALUE * var(--wp--custom--fxx)).

    While powerful, writing out that full calc() string every time we want to define a padding, margin, font-size, or width is tedious and prone to typos. To solve this, we use an SCSS function to write the boilerplate for us.

    The fxx() SCSS Function

    In our theme’s _functions.scss file, we define the fxx() helper function:

    /// Computes a fluid scale based on a provided base value to create proportional, viewport-relative sizing.
    @function fxx($value) {
        @return calc(#{$value} * var(--wp--custom--fxx));
    }

    How it Works

    1. Input ($value): The function takes a single argument. This is simply the pixel value given to you by the designer (e.g., just 24). Notice that we pass it as a raw number, without typing the px unit.
    2. Interpolation (#{$value}): This strange looking syntax (#{}) simply tells SCSS: “take the raw number passed into the function and print it here as text”.
    3. Output: The function returns the exact calc() string that the web browser needs in order to do the math.

    Using fxx() in Practice

    This function drastically simplifies our stylesheets. Designers can hand over a 1920px design, and developers can copy the pixel values verbatim, merely wrapping them in fxx().

    Without fxx() (Tedious):

    .hero-card {
        width: calc(600 * var(--wp--custom--fxx));
        padding: calc(40 * var(--wp--custom--fxx));
        margin-bottom: calc(24 * var(--wp--custom--fxx));
        border-radius: calc(16 * var(--wp--custom--fxx));
    }

    With fxx() (Clean & Maintainable):

    .hero-card {
        width: fxx(600);
        padding: fxx(40);
        margin-bottom: fxx(24);
        border-radius: fxx(16);
    }

    When Dart SCSS compiles this file (translating our SCSS code into the standard CSS that browsers actually understand), it transforms our clean fxx() calls back into the complex calc() strings.

    JavaScript Utility Parity

    Sometimes, styles need to be calculated or applied dynamically via JavaScript (for example, setting initial layouts for complex GSAP animations). To maintain consistency, we provide an identical utility in JS (src/js/utility.js):

    export const fxx = (value) => `calc(${value} * var(--wp--custom--fxx))`;
    
    // Usage:
    // element.style.gap = fxx(20);

    While 

    fxx() solves the problem of keeping layouts proportional, pure proportional scaling has a flaw: what happens when a screen gets too small, or too large? We’ll explore how to control these extremes using mathematical bounds in Part 3.

  • Fluid Scaling: The Core Concept

    In modern web design, creating layouts that look perfect on every screen size—from massive 4K monitors to small mobile phones—is a significant challenge. Traditional approaches rely heavily on fixed pixel values (e.g., width: 300px) combined with numerous media queries (@media (max-width: 768px) { ... }) to snap elements into different layouts at specific breakpoints.

    This “snapping” effect can feel abrupt and often leads to elements looking slightly off-proportion between breakpoints.

    Fluid scaling (often called proportional scaling) solves this by ensuring that elements smoothly grow and shrink in direct proportion to the viewport’s width.

    Think of your website like a rubber band. As you stretch the window (on a desktop) or compress it (on a phone), the elements inside should stretch and compress seamlessly along with it.

    The Mathematics of Fluid Scaling

    At the heart of our fluid scaling system is a simple mathematical ratio. It ties a specific pixel value to the width of the screen. In CSS, the full width of the screen is represented by 100vw (Viewport Width, meaning 100% of the visible screen).

    The core formula is: ( Target Pixel Value ) × ( 100vw / Base Design Width )

    Example Scenario

    Let’s say our designer created a mockup in Figma with an artboard width of 1920px (our Base Design Width). In that design, a specific heading has a font size of 32px (our Target Pixel Value).

    We want that heading to be exactly 32px only when the screen is exactly 1920px wide. If the screen shrinks perfectly in half to 960px, we want the font size to intuitively shrink in half to 16px. This guarantees the design always looks exactly like the mockup, no matter the device.

    Plugging it into the formula: 32 * ( 100vw / 1920 )

    1. The ratio (100vw / 1920) essentially figures out “what percentage of the base design width is the current screen?”
    2. If the user’s screen is 1920px wide, 100vw equals 1920px. The ratio becomes (1920 / 1920) = 1. Then, 32 * 1 = 32px.
    3. If the user’s screen is 960px wide, 100vw equals 960px. The ratio becomes (960 / 1920) = 0.5. Then, 32 * 0.5 = 16px.

    The CSS Variable (--wp--custom--fxx)

    To avoid writing (100vw / 1920) everywhere in our CSS, we abstract this ratio into a global CSS custom property (variable) named --wp--custom--fxx.

    This variable holds the exact mathematical ratio. In our case, the value it holds is exactly calc(100vw / 1920).

    Defining the Variable in WordPress (theme.json)

    If you are building a modern WordPress block theme, you don’t define this variable in a standard style.css file. Instead, you define it in the theme.json configuration file.

    Doing it this way is highly beneficial because it allows WordPress to automatically make this variable available inside the Gutenberg Site Editor. This means your content creators will see the exact same fluid scaling in the backend editor as the visitors see on the live site.

    To add this to your theme, insert the following into the settings object of your theme.json:

    {
      "$schema": "https://schemas.wp.org/trunk/theme.json",
      "version": 3,
      "settings": {
        "custom": {
          "fxx": "calc(100vw / 1920)"
        }
      }
    }

    Note: When you define a custom object named fxx inside settings.custom, WordPress automatically generates a CSS variable and prefixes it with --wp--custom--. This is where --wp--custom--fxx physically originates and how it gets injected into the <body> of your website.

    Once defined, this variable makes the math cleaner everywhere else. Anywhere we want to scale a value based on the 1920px design, we simply multiply our target pixel value by this variable using the calc() function:

    .my-element {
      /* Scales a 300px box down proportionally on smaller screens */
      width: calc(300 * var(--wp--custom--fxx));
    }

    In the next part, we’ll look at how the SCSS 

    fxx() function makes writing this even easier and cleaner.

  • Creating Outlined Text Effects with CSS Text Stroke

    Typography plays a crucial role in modern web design. With the right styling, even a simple text element can serve as a strong visual anchor for your layout. One effective yet often overlooked technique is the use of CSS text stroke, which allows developers to add outlines around text — creating clean, bold, and visually distinctive headlines without relying on images.

    The -webkit-text-stroke CSS property lets you define both the width and color of a text outline. It serves as a shorthand for the individual properties -webkit-text-stroke-width and -webkit-text-stroke-color.

    This article demonstrates how to achieve a text stroke effect using CSS, along with a practical example.

    The HTML Structure

    We start with a minimal HTML setup:

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>HTML + CSS</title>
        <link rel="stylesheet" href="styles.css" />
      </head>
      <body>
        <h1>Jaspreet Kaur</h1>
      </body>
    </html>
    

    This example keeps the structure intentionally simple. The focus is on applying style to the <h1> element, which serves as our primary visual element.

    Applying the CSS

    The visual transformation occurs entirely through CSS:

    @import url("https://fonts.googleapis.com/css2?family=Zain:ital,wght@0,200;0,300;0,400;0,700;0,800;0,900;1,300;1,400&display=swap");
    
    h1 {
      -webkit-text-stroke: 2px #0d9a66;
      text-stroke: 2px #0d9a66;
      font-size: 100px;
      line-height: 1;
      color: #fff;
      font-family: "Zain", sans-serif;
      font-weight: 700;
    }

    Key Properties

    • Font Import: The @import rule pulls in the Zain typeface from Google Fonts, chosen for its contemporary yet readable style.
    • Text Stroke: The property -webkit-text-stroke (and its unprefixed form, where supported) defines the outline of the text. In this case, a 2px stroke in #0d9a66 — a rich green — outlines the white text for a clean, modern appearance.
    • Typography Settings: Setting a large font size (100px) and bold weight (700) ensures the stroke effect is clearly visible.

    The Result

    The result is a bold heading displaying “Jaspreet Kaur” with a clean green outline. This simple effect gives the text a logo-like presence — elegant yet minimal.

    Such an approach is highly effective for:

    • Hero or landing page headlines
    • Personal branding and portfolio headers
    • Section titles that require visual emphasis

    By using pure CSS, developers can create scalable, resolution-independent text effects that perform well across devices.

    Browser Support and Fallbacks

    The text-stroke property is currently supported in most WebKit-based browsers (including Chrome, Edge, and Safari). However, it may not render in Firefox or some older browsers.

    For broader compatibility, a fallback using text-shadow can simulate a similar outline:

    text-shadow: 2px 2px 0 #0d9a66;

    While this method doesn’t replicate the crisp edges of text stroke, it ensures visual consistency across more environments.

    Conclusion

    The -webkit-text-stroke property offers a simple yet powerful way to enhance typography on the web. By combining it with modern fonts and thoughtful color contrast, designers can create text that feels polished and professional without increasing page weight. While this method doesn’t replicate the crisp edges of text stroke, it ensures visual consistency across more environments.

    This technique demonstrates how minimal CSS can yield high visual impact — reinforcing that great design often comes from subtle, well-executed details.