Logo
componentA logo: a Picture of the image recipe, with an AVIF source then a WebP one when it has them, each a URL or a map of densities, its variant for a dark system and its still image where motion is reduced, linked to the home page when it has an href. {theme} and {locale} in its sources are replaced, so one line serves the logo of every theme and language.
Preview
Code
<twig:Logo src="/images/logo.png" webp="/images/logo.webp" alt="Studio" href="/" />
Code
<twig:Logo src="/images/logo.png" webp="/images/logo.webp" alt="Studio" href="/" />
Usage
Code
<twig:Logo src="{{ asset('images/logo.svg') }}" alt="Studio" />
Installation
php bin/console ux:install logo --kit=github.com/parler-haut-interagir-librement/ux-kit
It brings the recipes it needs: image
Props
| Prop | Type | Default | Description |
|---|---|---|---|
webp |
string|array<int|string,string>|null |
null |
A WebP source, offered after the AVIF one: a URL or a map of densities to URLs; "{theme}" and "{locale}" in it are replaced. |
avif |
string|array<int|string,string>|null |
null |
An AVIF source, offered first: a URL or a map of densities to URLs; "{theme}" and "{locale}" in it are replaced. |
dark |
string|array<int|string,string>|null |
null |
The logo drawn for a dark system, offered where prefers-color-scheme is dark: a URL or a map of densities to URLs; "{theme}" and "{locale}" in it are replaced. |
still |
string|array<int|string,string>|null |
null |
The still logo of an animated one, offered where prefers-reduced-motion is reduce: a URL or a map of densities to URLs; "{theme}" and "{locale}" in it are replaced. |
srcset |
string|array<int|string,string>|null |
null |
The densities of the fallback image, as HTML writes them or a map of densities to URLs; "{theme}" and "{locale}" in them are replaced. |
theme |
string|null |
null |
The theme written in place of "{theme}", such as "default" or "dark". |
locale |
string|null |
null |
The locale written in place of "{locale}", such as "fr". |
href |
string|null |
null |
A link around the logo, usually to the home page. |
width |
int|null |
null |
The width of the image, to reserve its space before it loads. |
height |
int|null |
null |
The height of the image, to reserve its space before it loads. |
loading |
string |
'eager' |
How the image loads: "eager" above the fold, "lazy" below it. |
Examples
By density
<twig:Logo
src="/images/1x/logo.png"
:srcset="{1: '/images/1x/logo.png', 2: '/images/2x/logo.png'}"
:avif="{1: '/images/1x/logo.avif', 2: '/images/2x/logo.avif'}"
:webp="{1: '/images/1x/logo.webp', 2: '/images/2x/logo.webp'}"
alt="Studio"
:width="160"
:height="40"
/>
By theme
The theme the page was given picks the logo drawn for its background.
<twig:Logo src="/images/logo-{theme}.svg" alt="Studio" :theme="theme" />
For a dark system
dark is offered where the system is dark, still where the reader reduces motion, before the other sources; each a
URL or a map of densities, its placeholders replaced.
<twig:Logo src="/images/logo.png" :dark="{1: '/images/logo-dark.png', 2: '/images/logo-dark@2x.png'}" alt="Studio" />
<twig:Logo src="/images/logo.gif" still="/images/logo.png" alt="Studio" />
By language
A logo that writes a translated name.
<twig:Logo src="/images/logo-{locale}.svg" alt="{{ 'site.name'|trans }}" :locale="app.request.locale" />
With an asset versioning strategy, resolve each variant with asset() instead, as the placeholders are replaced after
the URL is built.
Accessibility
alt is required: the logo's text alternative is the name it writes. It is empty only when that name is written next
to the logo, so that screen readers do not read it twice. Give width and height to reserve the logo's space.
Files to copy
templates/components/Logo.html.twig
{#-
# A logo: drawn through the Picture of the image recipe, with its AVIF and WebP sources and its densities, its variant
# for a dark system and its still image where motion is reduced, swapped by theme or locale, linked when it has an href.
#}
{%- props
## string The image shown where neither AVIF nor WebP is read, PNG or SVG; "{theme}" and "{locale}" in it are replaced.
src,
## string The text alternative, the name the logo writes; an empty string only when that name is written next to it.
alt,
## string|array<int|string,string>|null A WebP source, offered after the AVIF one: a URL or a map of densities to URLs; "{theme}" and "{locale}" in it are replaced.
webp = null,
## string|array<int|string,string>|null An AVIF source, offered first: a URL or a map of densities to URLs; "{theme}" and "{locale}" in it are replaced.
avif = null,
## string|array<int|string,string>|null The logo drawn for a dark system, offered where prefers-color-scheme is dark: a URL or a map of densities to URLs; "{theme}" and "{locale}" in it are replaced.
dark = null,
## string|array<int|string,string>|null The still logo of an animated one, offered where prefers-reduced-motion is reduce: a URL or a map of densities to URLs; "{theme}" and "{locale}" in it are replaced.
still = null,
## string|array<int|string,string>|null The densities of the fallback image, as HTML writes them or a map of densities to URLs; "{theme}" and "{locale}" in them are replaced.
srcset = null,
## string|null The theme written in place of "{theme}", such as "default" or "dark".
theme = null,
## string|null The locale written in place of "{locale}", such as "fr".
locale = null,
## string|null A link around the logo, usually to the home page.
href = null,
## int|null The width of the image, to reserve its space before it loads.
width = null,
## int|null The height of the image, to reserve its space before it loads.
height = null,
## string How the image loads: "eager" above the fold, "lazy" below it.
loading = 'eager'
-%}
{%- set _swap = {} -%}
{%- if theme is not null %}{% set _swap = _swap|merge({'{theme}': theme}) %}{% endif -%}
{%- if locale is not null %}{% set _swap = _swap|merge({'{locale}': locale}) %}{% endif -%}
{%- set _urls = {avif: avif, webp: webp, srcset: srcset, dark: dark, still: still}|map(value => value is iterable ? value|map(url => url|replace(_swap)) : (value is null ? null : value|replace(_swap))) -%}
{%- set _sources = [] -%}
{%- if _urls.avif is not null %}{% set _sources = _sources|merge([{type: 'image/avif', srcset: _urls.avif}]) %}{% endif -%}
{%- if _urls.webp is not null %}{% set _sources = _sources|merge([{type: 'image/webp', srcset: _urls.webp}]) %}{% endif -%}
{%- set _tag = href is null ? 'span' : 'a' -%}
<{{ _tag }}{% if href is not null %} href="{{ href }}"{% endif %}{{ attributes.defaults({class: 'isLogo'}) }}>
{{- component('Picture', {src: src|replace(_swap), alt: alt, width: width, height: height, srcset: _urls.srcset, sources: _sources, dark: _urls.dark, still: _urls.still, loading: loading}) -}}
</{{ _tag }}>