Skip to content
tinytip

Latest tips / 6

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

How to get the event target inside Shadow DOM

March 3, 2022
#javascript #events #shadowdom

The event object in JavaScript has a target property which is the actual element that triggered the event. The currentTarget property is the element that the event listener is attached to.

<div id="container">
<button>Click Me</button>
</div>
document
.getElementById("container")
.addEventListener("click", (event) => {
console.log("target", event.target); // => button
console.log("currentTarget", event.currentTarget); // => div
});

This works different when using Shadow DOM. When the event was triggered inside an element with Shadow DOM, the target property points the Shadow DOM element, not the element that triggered the event:

<div id="container">
<!-- Web Component with Shadow DOM -->
<my-button>Click Me</my-button>
</div>
document
.getElementById("container")
.addEventListener("click", (event) => {
console.log("target", event.target); // => my-button
console.log("currentTarget", event.currentTarget); // => div
});

While this is good in terms of encapsulation, there are use cases where you need the actual target. In these cases you can use the composedPath method to get the actual target:

document
.getElementById("container")
.addEventListener("click", (event) => {
console.log("path", event.composedPath());
// => [slot, button, document-fragment, my-button,
// div#container, body, html, document, Window]
});

The method returns all the elements that are in the path of the event. The first element is the one that triggered the event.

Note: this works only if the Shadow DOM uses encapsulation mode open.