Your Cypress component tests render every component in Times New Roman. Why?
answer
- The mount page has its own head
- Nothing from index.html came along
- Copy the link tags across
- A local font file must be served
- Network panel: 404 or no request
basics
~20 sFonts usually arrive through link tags in the application's index.html, and Cypress mounts components into cypress/support/component-index.html instead, which has none of them. Copy the same link tags there, and make sure local font files are served by the dev server.
solid answer
~40 sCypress renders components into `cypress/support/component-index.html`, which ships as a bare page: charset, viewport, title, root element. Every `<link>` or `@import` your application's real `index.html` uses to pull in a font is missing, so the browser falls back to its default serif. Copy those head tags into the Cypress index file. If instead the fonts come from local `@font-face` files, there is a second failure: the file has to be served by the dev server Cypress started. Under Vite, put the files in the public directory and use root-relative URLs; under webpack, `webpack-dev-server` serves no static directory unless its `static` option names one. Check the network panel — a 404 and no request at all mean different things.
code
html · 18 lines<!-- cypress/support/component-index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Components App</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Readex+Pro&display=swap"
rel="stylesheet"
/>
</head>
<body>
<div data-cy-root></div>
</body>
</html>go deeper
Know that Cypress mounts components into its own index HTML file, and that fonts and stylesheets loaded by the application's page do not come along for free.
Explain the difference between a font that arrives through a head link and one that arrives through a local font-face file, because the fix is different in each case.
Show a diagnosis order: network panel first, computed styles second, head diff third, component last. Say why a fallback font can break layout and visibility assertions.
Decide how much of the application's head the harness reproduces as policy, and how a team keeps two head definitions from drifting apart over years.
## Where an application's fonts actually come from There are two routes, and they behave very differently under a component harness: - **The application's `index.html` head loads them** — a `<link rel="stylesheet">` pointing at a font service, a pair of `<link rel="preconnect">` hints, or an `@import url(...)` inside a `<style>` block. - **A stylesheet declares `@font-face` rules** pointing at local files (`.woff2`, `.woff`, `.ttf`) that the build serves from a public directory. ## Why the mount page has neither Cypress renders components into `cypress/support/component-index.html`, and the scaffolded version of that file has a charset, a viewport meta tag, a title and a root element — nothing else. Nothing from your application's own `<head>` is there unless you put it there. The result is a suite that is subtly wrong rather than obviously broken. A data grid designed at a condensed weight falls back to the browser's default serif, and every measurement built on that font moves with it: row height, column truncation, whether a header still fits, whether Cypress considers an element visible. The component is fine. The page it was mounted into is not the page it was designed for. If the font arrived by the first route, the fix is close to literal: copy the same `<link>` and `@import` lines into the Cypress index file, in the same order, so the head content that the whole application depends on exists in both pages. ## A local font file still has to be served The second route has an extra failure mode. The `@font-face` rule loads, the browser dutifully requests the file, and the request 404s — because the dev server Cypress started is not the server that serves your app in development, and its static-file behaviour belongs to the bundler, not to Cypress: - **Vite**: put the font files in the project's public directory and reference them with root-relative URLs such as `url('/fonts/grid-condensed.woff2')`. Cypress sets Vite's `base` to match `devServerPublicPathRoute` (default `/__cypress/src`), and Vite rewrites root-relative asset URLs accordingly. - **Webpack**: `webpack-dev-server` serves no static directory by default. Either `import` the font from a module so webpack emits it as an asset, or add a `static` entry to the `devServer` section of your webpack config so the directory is served. Icon fonts behave identically and are usually noticed later, because a missing glyph reads as a layout quirk rather than a wrong typeface: buttons keep their labels, and the icon slot renders a tofu box or an unstyled ligature. If your design system ships icons as a font rather than as inline SVG, treat it as a second font to account for, not as part of the first. One knob is worth knowing about and worth leaving alone. `devServerPublicPathRoute` is the URL prefix Cypress uses to serve compiled specs and assets, and Cypress feeds it to Vite's `base`. Changing it is occasionally necessary when an application's own public path must match, but an incorrect value stops specs and assets loading at all, with failures that look nothing like a path problem. ## Diagnosing it in order 1. Open the browser's network panel during the mount and filter for the font request. A 404 means the rule loaded but the file is not being served; **no request at all** means the `@font-face` rule or the `<link>` never reached the page. 2. Read the computed `font-family` on the element. If your family is listed and the text still renders as a fallback, the declaration is present and the file failed. 3. Diff the mount page's `<head>` against the application's `index.html`. Every `<link>`, `@import` and preconnect the app has and the index file lacks is a candidate. 4. Only then look at the component. A font problem is almost never the component's fault. ## What to mirror, and what to leave out - **Mirror** head content the whole UI depends on: font links, icon-font stylesheets, a vendor theme, a normalize sheet loaded by `<link>`. - **Leave out** analytics tags, error-reporting snippets and anything else that phones home. A component run has no business sending page views, and each one adds latency and a network dependency to every spec. - **Do not** paper over a missing font with a test-only `font-family` override in the support file. The suite then passes against a layout no user will ever see, which is worse than a red run. - **Be clear what a correct font buys you.** It makes the mount behave like production for measurement and visibility. It does not turn the render into an approved picture — a styled mount is evidence that the styles compiled and applied, not a baseline image.
- Should the Cypress index file also carry the app's analytics and error-reporting tags?No. Copy the head content the UI depends on — font links, icon fonts, a vendor theme, a normalize sheet — and leave out anything that phones home. A component run should not be sending page views or error reports, and those scripts add latency and an external network dependency to every spec for no testing value.
- How would you stop the Cypress index file drifting from the application's index.html?Keep the shared head content in one place both pages can use — a partial your build injects, or one stylesheet that carries the `@import` rules — so there is a single list rather than two. Where duplication is unavoidable, put a comment in each file pointing at the other, and review the pair together whenever the application's head changes.
saying these in an interview costs you the question
- Assumes Cypress serves the application's index.html to component tests
- Overrides font-family in the support file to make the suite pass
- Never opens the network panel to see whether the font 404s
- Thinks a component's own stylesheet should declare the app's web fonts
- Treats the wrong font as cosmetic when layout assertions depend on it