Images, Fonts and View Configuration

view.xml sets product image dimensions; where theme assets live, and why a resized image needs a command to appear.

Syntax<theme_dir>/etc/view.xml → <media><images module="Magento_Catalog"><image id="..." type="...">

Product images are not rendered at their uploaded size. Each place an image appears asks for a named size, and the sizes are declared in view.xml — view configuration, the theme's file of display settings. It lives at <theme_dir>/etc/view.xml and merges with the modules' and the parent themes' copies, so you declare only the entries you change.

How an image size is chosen

Inside <media>, each <image> has an id and a type. The id is the name the template or block asks for, such as category_page_grid or product_page_main_image. The type is the image role on the product: image, small_image, swatch_image, swatch_thumb or thumbnail. Width and height are pixels; constrain, aspect_ratio, frame, transparency and background control the fitting. Resized copies are cached under pub/media/catalog/product/cache.

Where the other assets live

Fonts go in <theme_dir>/web/fonts, images in <theme_dir>/web/images, scripts in <theme_dir>/web/js. These are static files, so they are served from pub/static and need a deploy outside developer mode.

What trips people up

A size change in view.xml does not touch images already cached. Run bin/magento cache:flush and then bin/magento catalog:images:resize, which rebuilds the cache from the current configuration. And the id must be the one that page uses: editing category_page_grid changes nothing on the product page.

Example

Example · xml
<!-- app/design/frontend/Acme/storefront/etc/view.xml -->
<view xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:Config/etc/view.xsd">
    <media>
        <images module="Magento_Catalog">
            <!-- Product tiles in a category grid. Luma ships 240x300. -->
            <image id="category_page_grid" type="small_image">
                <width>300</width>
                <height>375</height>
            </image>
            <!-- Main image on the product page. Luma ships 700x560; Blank ships 700x700. -->
            <image id="product_page_main_image" type="image">
                <width>900</width>
                <height>900</height>
            </image>
        </images>
    </media>
    <vars module="Magento_Catalog">
        <!-- Blank sets 1, which pads non-square images with white -->
        <var name="product_image_white_borders">0</var>
    </vars>
</view>

<!--
    On the storefront: category tiles and the product page image are served at
    the new dimensions, without white padding.

    Apply it with:
      bin/magento cache:flush
      bin/magento catalog:images:resize
    The second command rewrites pub/media/catalog/product/cache and takes a
    while on a large catalog.
-->

When to use it

  • Product photos look soft on a retina layout because the theme serves 240px tiles.
  • Non-square product images arrive padded with white borders in the category grid.
  • Add a licensed webfont to a theme without loading it from a third-party host.
  • Swap the header logo for one shipped with the theme rather than uploaded in the admin.

More examples

A font that ships with the theme

Put the font files in <theme_dir>/web/fonts and declare them with the UI library's .lib-font-face() mixin. @{baseDir} is resolved by Magento's preprocessor to the theme's own web directory, so the same declaration keeps working when the file is served from pub/static under a different path. Give @font-path without an extension; the mixin adds .woff2 and .woff. Outside developer mode the font files need a static deploy before the browser can fetch them.

Example · less
// app/design/frontend/Acme/storefront/web/css/source/_extend.less

//  Files: web/fonts/acme-sans/acme-sans-regular.woff2 (and .woff)
//         web/fonts/acme-sans/acme-sans-bold.woff2    (and .woff)

.lib-font-face(
    @family-name: 'Acme Sans',
    @font-path: '@{baseDir}fonts/acme-sans/acme-sans-regular',
    @font-weight: 400,
    @font-style: normal,
    @font-display: swap
);

.lib-font-face(
    @family-name: 'Acme Sans',
    @font-path: '@{baseDir}fonts/acme-sans/acme-sans-bold',
    @font-weight: 700,
    @font-style: normal,
    @font-display: swap
);

body {
    font-family: 'Acme Sans', @font-family__sans-serif;
}

A logo from the theme instead of the admin

The header logo block falls back to images/logo.svg inside the theme, so the simplest route is to place your file at <theme_dir>/web/images/logo.svg. When the filename differs, pass it as a layout argument: logo_file is a path relative to the theme's web directory, and logo_alt sets the alt text. A logo uploaded in Content > Design > Configuration takes precedence over both, which is the usual reason a layout change appears to do nothing.

Example · xml
<!-- app/design/frontend/Acme/storefront/Magento_Theme/layout/default.xml -->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="logo">
            <arguments>
                <argument name="logo_file" xsi:type="string">images/acme-logo.svg</argument>
                <argument name="logo_alt" xsi:type="string">Acme</argument>
            </arguments>
        </referenceBlock>
    </body>
</page>

<!--
    File: app/design/frontend/Acme/storefront/web/images/acme-logo.svg
    Apply: bin/magento cache:flush
           bin/magento setup:static-content:deploy -f en_US   (outside developer mode)
-->

Gallery behaviour, not just sizes

view.xml also carries display variables, read through the view configuration rather than core_config_data. The Magento_Catalog gallery block uses these for the product page gallery: navigation style, looping, arrows and fullscreen behaviour. Changing them is a theme decision, which is why they sit here and not in the admin. A cache flush is enough, since no images are regenerated.

Example · xml
<!-- app/design/frontend/Acme/storefront/etc/view.xml -->
<view xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:Config/etc/view.xsd">
    <vars module="Magento_Catalog">
        <var name="gallery">
            <var name="nav">thumbs</var>
            <var name="loop">false</var>
            <var name="arrows">false</var>
            <var name="navdir">vertical</var>
            <var name="transition">
                <var name="effect">dissolve</var>
                <var name="duration">300</var>
            </var>
        </var>
    </vars>
</view>

Discussion

  • Be the first to comment on this lesson.