Rethinking Textual content Resizing on Internet. Airbnb has made vital strides in… | by Steven Bassett | The Airbnb Tech Weblog | Might, 2024
To higher perceive the accessibility problem, allow us to discover how browser zoom performance works. It’s possible you’ll already be aware of this function, utilizing keyboard shortcuts like Command / Ctrl + or Command / Ctrl — to scale all content material inside a window. Once you enhance the zoom stage past 100%, the viewport’s peak and width proportionally lower, whereas the content material is blown as much as match the bigger window.
As a part of our accessibility testing technique, we had been utilizing browser zoom to check the usability of our pages each on desktop and cellular sizes. Desktop testing confirmed that our pages did comparatively effectively on the 200% zoom stage with our responsive net method throughout the location. We noticed fewer points within the general consumer expertise when in comparison with cellular net.
This works effectively on desktop, the place we serve a smaller breakpoint (e.g., large to compact) and the viewport is comparatively spacious. Nonetheless, the restrictions of browser zoom turn out to be extra pronounced on cellular net, the place the viewport is smaller. If we had been to scale the content material in a cellular viewport, it must match right into a viewport that’s half the width and half the peak of the unique. This may end up in vital accessibility points, because the textual content and UI parts turn out to be extraordinarily tough to learn and work together with. As proven within the picture on the precise, the power to view even a single itemizing inside a display screen’s price of area isn’t doable with out scrolling, resulting in a irritating expertise.
Font scaling is the time period we’ll use to explain the power to regulate textual content measurement independently of general web page zoom. In contrast to browser zoom, which scales all content material proportionally, Font Scaling applies solely to the textual content parts on the web page. This permits customers to customise the font measurement to their most well-liked studying measurement with out affecting a lot of format or responsiveness of the remainder of the content material.
Font Scaling, can also be the time period we are going to use for scaling the font primarily based on a consumer’s most well-liked measurement. In contrast to zoom, this setting shall be utilized to all websites. Beneath is an instance of how the font scaling applies to only the textual content on the display screen, displaying that the one scale of the textual content will increase, as a substitute of all of the content material.
Video Description: Airbnb textual content is scaled by setting the font measurement on arc browser, displaying the scaling from 16px to 32xp.
This idea of unbiased font scaling is much like the Dynamic Kind function on iOS, as we mentioned in our weblog put up “Supporting Dynamic Kind at Airbnb”. Dynamic Kind permits customers to set a most well-liked system-wide textual content measurement, which then mechanically adjusts the font measurement throughout all suitable apps.
Contemplating our current methods for accessibility on iOS, incorporating font scaling (vs zoom scaling) into our net accessibility method was a pure subsequent step to assist add parity in approaches throughout our platforms.
Now that we perceive why font scaling is so highly effective for cellular net, we must always deal with why we would select one CSS size unit over one other for supporting font scaling. On this weblog put up we’re solely going to deal with px, em and rem however there are different models as effectively. CSS size models are linked to font scaling as a result of they decide how textual content and different parts are sized on an online web page. Some size models are fastened, that means they don’t change primarily based on the consumer’s font measurement settings, whereas others are relative, that means they scale proportionally with the font measurement.
Let’s take a deep take a look at 3 CSS size models and the way they relate to font scaling:
- px models are essentially the most generally used on the net, theoretically they need to symbolize one pixel on the display screen. They’re a hard and fast unit that means the rendered worth doesn’t change.
- em models nonetheless are a relative unit which can be primarily based on the mother or father component’s font measurement. The identify ‘em’ comes from the width of the capital letter ‘M’ in a given typeface, which was historically used because the reference level for font sizes. 1 em unit is the same as the peak of the present font measurement, roughly 16px on the default worth. em models scale proportionally, to allow them to be affected by their mother or father’s font sizes
- rem models, brief for “root em”, are much like em models in that they’re proportional to font measurement, however they solely use the foundation component (the html component) to calculate their font measurement. Which means rem models provide font scaling, however should not affected by their mother or father’s font measurement.
The selection between em and rem models typically comes right down to the extent of management and predictability required for font scaling. Whereas em models can be utilized, they will result in cascading font measurement adjustments that could be tough to handle, particularly in complicated layouts. In distinction, rem models present a extra constant and predictable method to font scaling, as they’re at all times relative to the foundation component’s font measurement.
That is illustrated within the CodePen instance, the place the completely different font scaling behaviors of px, em, and rem models are demonstrated. In conditions the place font scaling is a important requirement, such because the Airbnb instance talked about, the usage of rem models generally is a extra dependable selection to make sure a constant and maintainable font scaling resolution.
Relative models like rem can be utilized anyplace a hard and fast unit like px can be utilized. Nonetheless, indiscriminate use of rem models throughout all properties can result in undesirable scaling habits and elevated complexity.
Within the case of Airbnb, the workforce determined to prioritize the usage of rem models particularly for font scaling, somewhat than scaling all parts proportionally. This focused method supplied the important thing good thing about constant textual content scaling, with out the potential downsides of scaling each facet of the format.
The rationale behind this resolution was twofold:
- Scaling the whole lot utilizing rem models would have been much like Browser Zoom and doubtlessly launched unintended format points,
- The first focus was on offering a mobile-friendly font scaling resolution. By concentrating on font sizes with rem models, the workforce might make sure that crucial content material — the textual content — scaled appropriately.
Shifting from pixel-based values to rem models as a company-wide change in CSS observe generally is a vital problem, particularly when working throughout a number of groups. The effort and time required to teach designers and frontend builders on the brand new method, and to have them convert their current pixel-based values to rem models, generally is a vital barrier to adoption. To deal with this, the Airbnb workforce determined to deal with automating the unit conversion course of as a lot as doable, enabling a extra seamless transition to the brand new rem-based system.
As an alternative of requiring designers to have to consider new models or introduce some conversion for net solely, we determined to proceed to writer our CSS in px models. This lowered the quantity of coaching required for groups to begin utilizing rem models out the gate.
One space we did deal with with our design groups was beginning to check their designs utilizing font scaling by leveraging the Text Resizer — Accessibility Checker to assist simulate what a design would possibly appear to be at 2X the font measurement. This instrument helped us spot issues earlier into the design course of.
Airbnb is within the strategy of transitioning from React-with-Styles to a more moderen method utilizing Linaria. Whereas the adoption of Linaria was progressing rapidly, we acknowledged the necessity to assist each styling methods for a constant expertise. Managing the conversion throughout these two completely different CSS-in-JS methods posed a further problem.
Linaria
By leveraging Linaria’s assist for CSS customized properties, the workforce was in a position to create new typography theme values that mechanically transformed the prevailing pixel-based values to their rem equivalents. This method allowed the workforce to introduce the brand new rem-based theme values in a centralized method, making them out there to baby parts. This gave the workforce the power to override the rem values on a per-page foundation, offering the required flexibility through the transition course of.
import { typography } from './site-theme';// Loops by means of the CSS Vars we use for typography and converts them
// from px to rem models.
const theme: css`
${getCssVariables({ typography: replacePxWithREMs(typography) })}
// Modifications from:
// - body-font-size: 16px;
// To
// - body-font-size: 1rem;
`;
// Use the category identify generated from linaria to override the theme
// variables for the youngsters of this part.
const RemThemeLocalProvider: React.FC = ({ youngsters }) => {
const cx = useCx();
return <div className={linariaClassNames.theme)}>{youngsters}</div>;
};ty
Though this method helped us convert many of the font scaling properties, there have been many locations in our code that we used pxbased values exterior the theme. Linaria’s assist for post-CSS plugins made fixing these areas comparatively straightforward. We leveraged postcss-pxtorem to assist goal these values extra simply. We began by utilizing an permit record, in order that we might fastidiously apply this variation to a smaller set of early adopting pages.
It was essential that we supplied an escape hatch when there was some purpose for front-end engineers needing to make use of px models. Fortunately we had been in a position to present this by utilizing a unique casing for the px worth like proven under.
/* `px` is transformed to `rem` */
.convert {
font-size: 16px; /* transformed to 1rem */
}
/* `Px` or `PX` is ignored by `postcss-pxtorem`
however nonetheless accepted by browsers */
.ignore {
font-size: 200Px;
font-size: clamp(16Px, 2rem, 32Px);
}
React with Kinds
A great quantity of our frontend code nonetheless makes use of react-with-styles, so we needed to discover one other strategy to assist these instances with a simple conversion. By this we created a easy Greater-Order part that made the conversion fairly simple. First we created a wrapper for the withStyles operate like under, and gave the power to keep away from conversion as effectively.
export const withRemStyles = (
styleFn?: Nullable<(theme: Theme) => Kinds>,
choices?: WithStylesOptions & { disableConvertToRemUnits?: boolean },
) => {
const disableConvertToRemUnits = getDisableConvertToRemUnits(choices);
// If conversion is disabled, simply return the unique withStyles operate
if (disableConvertToRemUnits) {
return _withStyles(styleFn, choices);
}
// In any other case, wrap the unique model operate with a brand new operate
// that converts px to rem
return _withStyles((theme: Theme) => {
if (styleFn) {
const types = styleFn(theme);
const remStyles = convertToRem(types);
return remStyles;
}
return {};
}, choices);
};
Then the convertToRem will look by means of the keys and values and map a transformed worth for any of the font sizing attributes. This allowed us to automate the conversion course of in a extra simple method.
With these two challenges out of the best way, we will begin testing our parts to confirm if there are any main points we would must resolve earlier than rolling out. In our part documentation and tooling, we constructed an inner plugin to permit for simpler testing by setting the font-size on the html component straight to check with font scaling.
Screenshot testing has helped our groups catch visible regressions. Including assist to permit for setting extra screenshots at completely different root font sizes has helped our product groups overview what the part seems to be like at completely different font scales. To do that, we permit for including extra font sizes to be set when capturing the screenshots so that you don’t need to create new part variations only for font scaling.
Supporting font scaling for Cellular Safari was tougher. In contrast to different browsers, there’s not a font measurement choice out there in Cellular Safari. Nonetheless, they’ve launched assist for their very own font: -apple-system-body however there are some essential issues.
Since macOS Excessive Sierra (10.13), desktop Safari additionally helps the font choice, however there’s not a simple “font measurement” configuration out there in MacOS. As a result of there might be surprising habits on desktop Safari, so we used a @helps assertion to forestall this. The code under will solely goal Cellular Safari.
// Apple's Dynamic Kind requires this font household for use
// Solely goal iOS/iPadOS
@helps (font: -apple-system-body) and (-webkit-touch-callout: default) {
:root {
font: -apple-system-body;
}
}
One other consideration is that the “100%” default font measurement chosen doesn’t equal the usual font measurement of 16px, however somewhat 17px. It is a very delicate distinction, however it’s important for the design high quality bar we intention to realize at Airbnb. So to resolve this difficulty, we ended up utilizing an inline head script to normalize the worth, by putting it early into the web page execution we prevented seeing a change in font measurement.
(() => {
// do not do something if the browser does not match the helps assertion
if (!CSS.helps('(font: -apple-system-body) and (-webkit-touch-callout: default)')) return;
// Should create a component for the reason that root component types should not but parsed.
const div = doc.createElement('div');
div.setAttribute('model', 'font: -apple-system-body');
// Physique isn't out there but so this must be added to the foundation component
documentElement.appendChild(div);
const model = getComputedStyle(div);
if (model.fontSize === '17px') {
documentElement.model.setProperty('font-size', '16px');
}
documentElement.removeChild(div);
})();
Then when the web page masses we use a resize observer to detect if the worth adjustments once more to unset or set the font-size property on the html component. This helps us nonetheless assist scalable fonts, however not have a big influence on the default font measurement (100%).
Supporting scalable fonts is an funding that ought to make a dramatic distinction for our Hosts and company with low imaginative and prescient and anybody who advantages from bigger font sizes and management over their searching expertise. Beneath are two examples of the house web page displaying how the default font measurement (16px) seems to somebody who has blurry imaginative and prescient and what it seems to be like by doubling the font measurement (32px). The second picture is much extra legible and usable.