uberschrift ๐Ÿงข

GitHub

Zero-dependency magic heading levels for React and Vue.js

<Hx>I'm the h1!'</Hx>

<HxBoundary>
	<Hx>I want to be an h2</Hx>

	<HxBoundary>
		<Hx>I will be an h3</Hx>
	</HxBoundary>
</HxBoundary>
๐Ÿช„ โœจ
<h1>I'm the h1!'</h1>
<h2>I want to be an h2</h2>
<h3>I will be an h3</h3>

Motivation ๐Ÿคธ

Why heading levels (h1, h2, โ€ฆ) matter ๐Ÿ‘€

Grouping text sections underneath headings adds a logical hierarchy to the contents of a page, contributing to both accessibility and search engine optimization (SEO). Heading elements, ranging from <h1> to <h6>, represent different levels of importance and organization.

Properly nesting these elements ensures that screen readers and other assistive technologies can interpret and convey the content's structure to users with visual impairments, enhancing accessibility. Additionally, search engines rely on heading tags to understand the content hierarchy and relevance, influencing how they index and rank the page.

Consistent and well-ordered heading levels not only improve the overall readability of the document for both users and search engines but also contribute to a more efficient and user-friendly browsing experience.

Here's an example of a DOM structure with incorrect heading order:

<h1>This is the page's main heading โœ…</h1>

<h2>This is also fine โœ…</h2>

<h4>This should have been preceded by an h3! โŒ</h4>

If you want to learn more about this, check out the article in our blog: Heading for Greatness โ€” A React Developer's Guide to HTML Headings!

Why is dealing with heading levels difficult? ๐Ÿคท

In React projects, component encapsulation often makes chosing the right heading level within these components hard. They are often nested in an unforeseeable way, so the heading you chose to be an <h3> could now be used outside of the boundary of an <h2>, messing up the order.

How does uberschrift help? ๐Ÿงข

uberschrift provides you with two components: one we call <Hx> (as in "heading level x") that you should use for your headings; and one <HxBoundary> that you use to structure your document. Within these boundaries, <Hx> always choses the correct heading level. If you need to structure your document one level deeper, you wrap your component in a new <HxBoundary>.

We're borrowing this idea from Tenon-UI โค๏ธ.


Usage ๐Ÿ› ๏ธ

โš›๏ธ React

npm install uberschrift

Example ๐Ÿ“‡

page.tsx:

import { Hx, HxBoundary } from "uberschrift";

<Hx>Outside of the top level: this will be an h1</Hx>
<HxBoundary>
	<Hx>Within the top level: this will be an h2</Hx>

    <HxBoundary>
    	<Hx>Within the 2nd level: this will be an h3</Hx>
    </HxBoundary>

</HxBoundary>

๐ŸŒฒ Vue.js

npm install vueberschrift

Example ๐Ÿ“‡

App.vue:

<script setup lang="ts">
import { Hx, HxBoundary } from "vueberschrift";
</script>

<template>
	<Hx>Outside of the top level: this will be an h1</Hx>
	<HxBoundary>
		<Hx>Within the top level: this will be an h2</Hx>

    	<HxBoundary>
    		<Hx>Within the 2nd level: this will be an h3</Hx>
    	</HxBoundary>

    </HxBoundary>

</template>

FAQ ๐Ÿคฏ

How can I use it with my UI library? ๐Ÿค”

We have examples for Chakra UI and Material UI. Essentially you can either use the context hook useHx (see below) or you can leverage Hx into another component.

Example for Chakra:

import { Hx, HxBoundary } from "uberschrift";
import { Heading as ChakraHeading, HeadingProps } from "@chakra-ui/react";

const Heading = (props: HeadingProps) => <ChakraHeading {...props} as={Hx} />;

// โ€ฆ

<Heading size="xl">โ€ฆ</Heading>;

How does it handle heading elements nested below the 6th level? 7๏ธโƒฃ

The HTML Spec only allows h1 through h6 as elements and for most documents this should be more than enough.

That being said: if you find yourself nesting deeper, you can make that possible by leveraging WAI-ARIA attributes, e.g.: <div role="heading" aria-level="7">โ€ฆ</div>. uberschrift does that for you.

If you want to style these elements, you can do it like this:

[aria-level="7"] {
	font-weight: bold;
}

How does it work under the hood? ๐Ÿš—

It's a simple use case of React Context: HxBoundary is merely a nestable context provider, that increments the heading level.

In fact, you can use that context with useHx if you need it:

import { useHx } from "uberschrift";

const {
	Element, // string, e.g "h4"
	level, // number => 4
} = useHx();

Sponsors โค๏ธ

Peerigon GmbH


Legal Notice, reactExample