Skip to content
tinytip

Latest tips / 3

VoiceOver reads the title of external SVGs even if the alt text is empty

September 22, 2022
#a11y #svg

For accessibility reasons every image on a page should have an alt attribute with a description of the image or, for decorative images, with an empty value. Images with an empty alt text will be ignored by screen readers.

However, there is one exception. If the src attribute points to an SVG file that has a title tag, VoiceOver (on macOS and iOS) will read the title and not ignore the image.

<img src="circle.svg" alt="" />
<!-- /circle.svg -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg viewBox="0 0 20 10" xmlns="http://www.w3.org/2000/svg">
<circle cx="5" cy="5" r="5">
<!-- SVG image with a title tag -->
<title>Circle</title>
</circle>
</svg>

In the example above VoiceOver will read "Circle, image", while other screen readers like NVDA will ignore the image.

SVG files generated via design tools like Sketch often include a title. The title may be useless (like a description of a decorative icon) or even absolute nonsense (like an auto-generated UUID) and could also be in the wrong language, resulting in a confusing experience for screen reader users.

Either make sure that your images don't include a title tag or use the aria-hidden attribute to hide the image:

<img src="circle.svg" alt="" aria-hidden="true" />

RxJS combineLatest() accepts a selector function

July 12, 2022
#rxjs

The RxJS function combineLatest() accepts a selector function as last parameter. This selector function receives the latest value of each observable as argument and can be used to return a new value that will be emitted.

combineLatest(
// Array of observables
[stream1$, stream2$, stream3$],

// Selector function
(val1, val2, val3) => val1 + val2 + val3 // Return value will be emitted
).subscribe();

Import Markdown files in your Storybook MDX docs

June 23, 2022
#storybook #markdown

Storybook allows you to import existing Markdown files your MDX docs. You just need configure the transcludeMarkdown option in your storybook config:

// .storybook/main.js
module.exports = {
addons: [
{
name: "@storybook/addon-docs",
options: { transcludeMarkdown: true },
},
],
// ...
};

Then you can import your Markdown file in your MDX file and render it as a component:

import Example from "./Example.md";

# Hello World

<Example />

Use @at-root in SCSS to break out of nesting

June 23, 2022
#scss

In SCSS, selectors can be deeply nested. In some situations you may want to break out of the current selector hierarchy and emit some styles at the root of the document. SCSS provides the @at-root rule for this use case:

/* styles.scss */
@mixin some-mixin() {
color: black;

@at-root body {
background: lightgray;
}
}

.some-class {
@include some-mixin();
}

This will move body out of the parent selector:

/* styles.css */
.some-class {
color: black;
}

body {
background-color: lightgray;
}

Create collections from folders in Eleventy

June 23, 2022
#eleventy

If you want to create a collection from a folder in your Eleventy project, like a collection of blog posts in the posts folder, you could manually add a post tag to every post. But there is an easier way.

The Collection API in Eleventy lets you filter your pages by glob patterns:

module.exports = (eleventyConfig) => {
eleventyConfig.addCollection("posts", function (collectionApi) {
return collectionApi.getFilteredByGlob("posts/*.md");
});
};

This will create a collection "posts" that contains all the markdown files in the posts folder.