Skip to content
tinytip

Latest tips / 6

Eleventy supports Nunjucks globals

April 21, 2022
#eleventy #njk

Eleventy v1.0.0 (and above) supports Nunjucks globals. This lets you register a global value or function that is available in all Nunjucks templates.

module.exports = (eleventyConfig) {
// Register two globals, a static value and a function
eleventyConfig.addNunjucksGlobal("message", "Hello World");
eleventyConfig.addNunjucksGlobal("greeting", (name) => `Hello ${name}`);
}

Now you can use {{ message }} and {{ greeting('John') }} in your Nunjucks templates.

A more useful example is a global function that generates a unique id. You may need this if you want to connect a label with its input or for aria-labelledby and aria-describedby. Here I use the nanoid package to generate the id:

const { nanoid } = require("nanoid");
module.exports = (eleventyConfig) =>
eleventyConfig.addNunjucksGlobal("nanoid", () => nanoid());
};

Now you can create a new unique id, assign it to a local variable and use it to connect two HTML elements:

{% set id = nanoid() %}
<article aria-labelledby="{{ id }}">
<h2 id="{{ id }}">...</h2>
<p>...</p>
</article>

In the example above we connect the h2 with the article element using aria-labelledby.

Named lines in CSS grid

April 20, 2022
#css #grid

When creating a CSS grid with grid-template-columns you can give your grid lines a name using the square brackets syntax [name]. Child elements can be positioned using this name.

.grid {
display: grid;
/* Lines named "firstline", "secondline" and "thirdline" */
/* Last line has no name */
grid-template-columns: [firstline] 1fr [secondline] 1fr [thirdline] 1fr;
}

.child {
/* Use the line name to set the position */
grid-column: secondline;
}

A line can have multiple names by separating them with a space:

.grid {
grid-template-columns: [someline] 1fr [somename anothername thirdname] 1fr;
}

And using -start and -end suffixes you can let a line name span over multiple columns. In the example below left spans over the first two columns, center is used for the column in the middle and right spans over the last two columns.

.grid {
grid-template-columns:
[left-start] 1fr
[right-start center] 2fr
[left-end] 1fr [right-end];
}

.cell-left { grid-column: left; } /* 1fr + 2fr */
.cell-center { grid-column: center; } /* 2fr */
.cell-right { grid-column: right; } /* 2fr + 1fr */

And here is how this looks like:

Visualization of the CSS grid with named columns example.

Your child elements don't need to know the exact number of columns anymore and can instead use the line name. And if your grid is responsive and changes the number of columns dynamically, your child elements will still be positioned correctly without an additional media query to update grid-column.

React function component without children in TypeScript

March 26, 2022
#react #typescript

Update: Beginning with React 18 you don't need the VFC or VoidFunctionComponent interfaces anymore. The children property has been removed from the FC and FunctionComponent interfaces.

If you create a function component in React using TypeScript, there's the FC or FunctionComponent interface that you can use to define the type of your component. The interface automatically adds the children property to let the parent component pass child elements to your component.

If your component does not accept children, you can use the VCF or VoidFunctionComponent interface instead. It does not add the children property.

import { FC, VFC } from "react";

export interface Props {
msg: string;
}

export const MyCompWithChildren: FC<Props> = (props) => {
return <div>...</div>;
};

export const MyCompWithoutChildren: VFC<Props> = (props) => {
return <div>...</div>;
};

Run the same test with different data in Jest

March 15, 2022
#jest #testing
Credits: Matias Kinnunen

When you write a test in Jest and you want to run it with different data, you can use the test.each function. The function accepts a data table, which is an array of arrays with the arguments that are passed to the actual test function.

const table = [
["one", 1],
["two", 2],
["three", 3],
];

test.each(table)("converts %s to %d", (str, expected) => {
// Will be called 3 times with "one", "two", "three"
const result = convertToNumber(str);
expect(result).toBe(expected);
});

The title of the test can inject parameters with printf formatting (like %s for a string and %d for a number).

Read more about this in the Jest documentation.

Customize the PDF viewer when embedding a PDF

March 4, 2022
#html #pdf

If you want to embed a PDF document on your website you can use an iFrame. The browser will automatically render a PDF viewer.

Google Chrome, Firefox and Safari accept some parameters to customize the viewer. Add the parameters as part of the url fragment (after the #). Multiple parameters can be separated by &.

<iframe src="/path/to/document.pdf#toolbar=0"></iframe>

The following parameters are supported:

ParameterValueDescriptionSupport
toolbar1, 0Show or hide the toolbarChrome
viewFitV, FitH, FitChange the zoom level to fit (vertical, horizontal or both)Chrome
zoomnumberSet a specific zoom level in % (example: 300)Chrome, FF
pagenumberSet initial position to a specific page (example: 2)Chrome, FF, Safari
nameddeststringSet initial position to a named destination (like a heading)Chrome