Skip to content

Proposal: Decouple Heading Styles from Semantic HTML Elements #7405

Open
@ggdouglas

Description

@ggdouglas

Summary

This proposal aims to enhance the flexibility of Blueprint's heading components by decoupling their styles from the underlying semantic HTML elements. This change would allow developers to more easily align component appearance with design requirements while ensuring WCAG compliance by using appropriate semantic tags.

Problem Statement

Currently, Blueprint heading components are tightly coupled with specific HTML tags. For example, a <H1> component will render with a .bp5-heading class. This class is couples with the <h1> tag to define the size of the text:

h1.bp5-heading {
    font-size: 36px;
    line-height: 40px;
}

#{$tag}.#{$ns}-heading {
@extend %#{$tag};
}

The heading components are not much more than a simple wrapper component that applies this class:

export const H1 = htmlElement<HTMLHeadingElement>("h1", HEADING);
export const H2 = htmlElement<HTMLHeadingElement>("h2", HEADING);
export const H3 = htmlElement<HTMLHeadingElement>("h3", HEADING);
export const H4 = htmlElement<HTMLHeadingElement>("h4", HEADING);
export const H5 = htmlElement<HTMLHeadingElement>("h5", HEADING);
export const H6 = htmlElement<HTMLHeadingElement>("h6", HEADING);

It is common in UI development to want to visually de-emphasize a heading while keeping its semantic importance. This tight coupling of heading classes to elements can hinder both design flexibility and make it harder to adhere to good accessibility principles when aiming to implement a design.

Proposed Solution

  1. One lighter-weight option could be to expose classes that could be used to overwrite styles, e.g.
<H2 className={Classes.H6}>This H2 is sized like a H6</H1>

We would need to be careful in how we approach exposing/applying these classes in such a way that is not a breaking change.

Some other options to consider are mixins and/or exposing variables for typography sizes.

  1. Another common solution to this problem (seen in other component libraries) is to add a polymorphic prop like tagName or as:
<H6 tagName="h2">This H2 is sized like a H6</H1>
  1. A third solution could be to create a more generic "Typography" or "Text" component that can handle different sizing of text with semantics:
<Typography variant="h6" component="h2">
    This H2 is sized like a H6
</Typography>

References

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions