Understanding the Basics

Before diving into the specifics of rem and em, it's essential to grasp what these units represent:

  • EM: The em unit is relative to the font size of its closest parent element. This means if an element's font size is set to 2em, it will be twice the font size of its immediate parent element.
  • REM: The rem (Root EM) unit is relative to the root element's font size (html). This allows for a more consistent scaling across your website, as 1rem is always equal to the font size of the root element, regardless of the parentage of the element.

REM vs. EM: When to Use Which?

Use EM for:

  • Local scaling, particularly within components or elements where you want the size relative to a parent element rather than the root font size.
  • Styles that should scale directly in relation to their container's size.

Use REM for:

  • Global styling elements such as typography, margins, and paddings that you want to maintain consistent scaling across your site.
  • Setting up a responsive design where changing the root element's font size adjusts the scale of all dependent elements accordingly.

Practical Tips and Best Practices

  • Consistency is Key: Stick with one unit for a consistent type scale across your project. Mixing rem and em without a clear strategy can lead to unpredictability in your designs.
  • Accessibility Considerations: Use rem for global elements to ensure your website remains accessible, especially for users who adjust their browser's default font size.
  • Debugging: Use browser developer tools to inspect and debug font sizes and ensure your calculations are applied as expected.

Setting the Base Font Size

The base font size of your website is pivotal because it serves as the foundation for scaling your typography with rem and em units. Here's how to set it up:

Using the html Element

Traditionally, the base font size is set on the html element. This approach is particularly effective when using rem units because it provides a single reference point for the entire document.

html { font-size: 16px; } 

Using the :root Pseudo-Class

Alternatively, you can use the :root pseudo class for defining the base font size. 

:root { font-size: 16px; }

 Setting the base font size on the :root is a more modern method in CSS, which includes enhanced specificity and flexibility for defining global styles. 

Enhanced Specificity with :root

Higher Specificity: The :root pseudo-class targets the highest-level parent element in the document (the root of the document tree), which is the <html> element in HTML documents. Because :root is a pseudo-class, it has a higher specificity than the html type selector. This means that styles defined using :root can override those defined with the html selector if there is a conflict within the same stylesheet. This higher specificity is particularly useful when you need to ensure that certain base styles (like font sizes) are applied universally, overriding other potentially conflicting styles.

Flexibility and Scalability with :root

Global Variables: The :root selector is commonly used to define CSS custom properties (variables) that you want to be accessible globally across your entire stylesheet. This allows for a central control point over styles that need to be reused or dynamically adjusted. For example, setting a base font size as a variable means you can easily tweak it in one place, and this change will propagate throughout all styles that reference this variable.

Easier Maintenance: By using :root to define global constants like the base font size, you centralise these values, making your stylesheet easier to maintain and modify. This is particularly beneficial in larger projects or when implementing a design system where consistency across multiple components or pages is crucial.

Using CSS variables to set the Base Font Size

By defining a CSS variable for the base font size and then applying it to the font-size property on the :root selector, you're setting up a centralised control mechanism for your entire website's typography scaling. Here's how you can correctly implement this:-

Define the Variable

First, you declare the variable --base-font-size (or an alternative name like --body-font-size) under the :root pseudo-class. This makes the variable globally accessible across your entire stylesheet.

:root { --base-font-size: 16px; } 

Apply the Variable

Next, you use this variable to set the font-size property on the :root. This effectively sets the base font size for the website to the value stored in --base-font-size.

:root { --base-font-size: 16px; font-size: var(--base-font-size); } 

Why Use This Approach?

  • Maintainability: By using a CSS variable for the base font size, you can easily adjust the font size across your entire website by changing just one value. This is particularly useful for themes or responsive designs where you can adjust the base font size based on specific conditions or media queries.
  • Scalability: Using the : root font size in combination with rem units for other dimensions (like margins, paddings, or different font sizes) means that adjusting the --base-font-size will proportionally scale all related measurements. This provides a powerful tool for creating designs that need to adapt to various devices and screen sizes.
  • Responsiveness: You can further enhance this setup by adjusting the --base-font-size within media queries to change the base font size based on the viewport width, thereby improving the typography's responsiveness:
@media (max-width: 767px) {
  :root {
    --base-font-size: 14px; // Smaller base font size for smaller devices
  }
}

@media (max-width: 478px) {
  :root {
    --base-font-size: 12px; // Even smaller base font size for mobile devices
  }
}

This approach ensures that your typography and spacing scale correctly and coherently across different device sizes, improving your website's user experience and accessibility. Using CSS variables in this way streamlines the design process and enforces consistency throughout the design.

Webflow Users

You can easily set variables in Webflow to store and manage frequently used styles, but when setting the base font size in Webflow, know that Webflow sets a default body font size of 14px, smaller than the more common web default of 16px. For this reason, Webflow users should either set the --base-font-size variable on the Body (All Pages) Style selector or, for maximum flexibility, set the base font size on the :root in an HTML Embed and then round off the sizing by setting the Body (All Pages) font Size in the Style panel to 1 REM. 

:root {    
font-size: var(--base-font-size);
}
body {
font-size: 1rem; /* Webflow CSS Output or defined here */
}

Dynamic Font Sizing and Responsive Design

Adjusting the base font size and leveraging rem and em units can significantly enhance your website's responsiveness. This section will explore methods for dynamically manipulating font sizes and employing these units for a fluid and adaptable design.

Manipulating Base Font Size at Different Breakpoints

Responsive design often requires different font sizes at various screen widths. CSS media queries make it possible to adjust the base font size dynamically, which, in turn, adjusts all rem-based sizes accordingly.

:root {  
font-size: 16px; /* Default font size */
}
@media (max-width: 767px) { 
:root {    
font-size: 14px; /* Mobile */  
}
}

@media (max-width: 478px) {  
:root {
font-size: 12px; /* Mobile portrait */  
}
}

This approach ensures that text and elements are scaled proportionally in rem units, maintaining a harmonious layout across different device sizes.

JavaScript for Dynamic Adjustments

Beyond CSS, JavaScript offers more granular control over dynamic sizing, enabling real-time adjustments based on user interaction or other conditions.

window.addEventListener('resize', () => {
  const baseSize = Math.max(12, Math.min(18, window.innerWidth / 100));
  document.documentElement.style.fontSize = `${baseSize}px`;
});

This script adjusts the root font size based on the window width, ensuring the design remains responsive and accessible across a range of device sizes.

Advanced Responsive Techniques

Variable Fonts

You can create more complex responsive typography systems using CSS variables and the calc() function. For example, you can adjust font weight and size for different viewport widths.

:root {  
--font-weight-normal: 400;  
--font-weight-bold: 700;
}

@media (max-width: 767px) {  
:root {    
--font-weight-bold: 600; 
/* Lighter for small screens */  
}
}

Fluid Typography

Combining vw (viewport width) units with em and rem allows for fluid typography that scales seamlessly between specific breakpoints.

html { font-size: calc(1rem + 1vw); } 

This formula fluidly adjusts the base font size as the viewport width changes, offering a more responsive design without multiple breakpoints.

You can also create a more fluid base font size at different breakpoints using the calc() function and CSS variables on the body or the :root :-

@media screen and (max-width: 767px) {  
/* Tablet CSS */  
:root {  
font-size: calc(var(--base-font-size) * 0.8); /* 80% of initial font size */  
}
}

Leveraging EM for Component Scaling

Within components, em units can be advantageous for scaling elements relative to the component's font size rather than the global base size. This is particularly useful for self-contained components that need to maintain their proportions regardless of placement in the layout.

.component {  
font-size: 1.25rem; /* Base size for the component */
}
.component .child-element {
font-size: 0.8em; /* Scales based on the component's font size */
}

Conclusion

Mastering rem and em units in CSS allows for more flexible, accessible, and cohesive designs. Understanding the nuances between these units and how to set and adjust your base font size effectively will enable you to leverage CSS's full potential to enhance your web projects. Whether you opt for em units for localised scaling or rem units for global consistency, applying them thoughtfully and strategically to meet your design objectives is vital.