Typography

The typography styles reset and normalize the default user-agent property values for standard HTML content with mildly opinionated styles written to be customized using CSS variables and :where() for 0 specificity.

Global styles (anchor)

Margins have been reset to 0 and box-sizing properties values are set to border-box, and common properties for styles are reset with localised CSS variables for styling and to enable customizing them inline or in custom style sheets.

Localised variables
:where(html, body, h1, h2, h3, h4, h5, h6) {
  color: var(--color);
  font-size: var(--fs);
  font-weight: var(--fw);
  line-height: var(--lh);
}

:where(h1, h2, h3, h4, h5, h6, p, ol, ul, dl, address) {
  text-wrap: var(--tw);
  margin-block-end: var(--mb);
}

The default property values are provided as CSS variables that can be customized in the _configuration.scss document, see customizing below for more information and to view all the default typography styles.

Headings (anchor)

<h1>

The quick brown fox jumps over the lazy dog.

<h2>

The quick brown fox jumps over the lazy dog.

<h3>

The quick brown fox jumps over the lazy dog.

<h4>

The quick brown fox jumps over the lazy dog.

<h5>
The quick brown fox jumps over the lazy dog.
<h6>
The quick brown fox jumps over the lazy dog.

Paragraph text (anchor)

<p>

The quick brown fox jumps over the lazy dog.
ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz
123456789

<p>

The quick brown fox jumped over the lazy dog to leverage agile frameworks to provide a robust synopsis for high level overviews with iterative approaches to corporate strategy foster collaborative thinking.

Lists (anchor)

The styles for the default <ol>, <ul> and <dl> list types are written with element-specific CSS variables that can also be used to customize lists inline or in custom styles if required.

Ordered and unordered (anchor)

<ol>

  1. Item
  2. Item
  3. Item
  4. Item

<ul>

  • Item 1
  • Item 2
  • Item 3
  • Item 4

<ol style="--marker: upper-alpha;">

  1. Item
  2. Item
  3. Item
  4. Item

<ul style="--marker: square;">

  • Item
  • Item
  • Item
  • Item

<ol style="--pl: 3rem;">

  1. Item
  2. Item
  3. Item
  4. Item

<ul style="--pl: 1rem;">

  • Item
  • Item
  • Item
  • Item

Definition (anchor)

<dl>

Term 1
Description
Term 2
Description

<dl style="--dt-mt: .25rem;">

Term 1
Description
Term 2
Description

<dl style="--fw: bold;">

Term 1
Description
Term 2
Description

<dl style="--dd-ml: 0;">

Term 1
Description
Term 2
Description

Inline elements (anchor)

Standard inline <small> text uses a defined REM value included with the property variables below, small text within headings uses an EM value to scale the size to match each heading level.

Block elements (anchor)

<details>

Summary

Details body content

<blockquote>

Blockquote with author and citation.

— Editor Daily Blog

<hr>


<pre><code>*

html {
  color-scheme: light dark;
  font-family: system-ui, -apple-system, sans-serif;
  color: CanvasText;
  background-color: Canvas;
}

*The syntax highlighting colors demonstrated throughout the website for code examples uses Hugo's Chroma syntax highlighting and is currently not included with Themalize.

<figure> <img> with <figcaption>

Forest covered in snow with sunset filtering between tall trees.
Winter forest

Optional inclusions (anchor)

Included with the typography styles but disabled by default, each can be enabled as demonstrated below in the _configuration.scss document.

$enable-smooth-scroll: true;
$enable-view-transition: true; (not yet baseline)
$enable-vis-hidden: true;

The first two if enabled are included using the @media query (prefers-reduced-motion: no-preference) to respect a users preference for animation styles.

The third enables a .vis-hidden utility for making text available to assistive browsing but visually hiding it, and .vis-hidden-focus for the same purpose but making it viewable when focused. Each comes with a Sass @mixin that can be also used in custom CSS without the extension being enabled.

Extension utilities (anchor)

Seperate optional utilities are also available that extend and/or modify generic HTML typography elements using the styles and variables provided.

Customizing (anchor)

The default typography property values can be customized in the _properties.scss document, new values added must also be included with the typography Sass map in the _maps.scss document for compiling.

Properties

Themalize uses a responsive font sizing method learned from the CSS behind Jeremy Keith's website. The $font-size clamp() value is applied to the html tag and increases or decreases the fixed rem values used for the other font sizes depending on the viewport.

Adjust the clamp() values to alter font sizes globally and/or change the rem values as required. Please note changing font family may require adjusting all values to suit.

$font-family:         system-ui, -apple-system, Arial, Helvetica, sans-serif !default;
$font-size:           clamp(100%, 40% + 0.666vw, 140%) !default;
$body:                1rem !default;
$fs-xl:               1.25rem !default;
$fs-lg:               1.1rem !default;
$fs-sm:               0.906rem !default;
$fs-xs:               0.813rem !default;
$fs-xxs:              0.75rem !default;
$h1:                  2rem !default;
$h2:                  1.725rem !default;
$h3:                  1.5rem !default;
$h4:                  1.35rem !default;
$h5:                  1.2rem !default;
$h6:                  1.063rem !default;
$lh-body:             1.5 !default;
$lh-header:           1.2 !default;
Sass map
$typography: (
  "color": var(--text),
  "font": #{$font-family},
  "fs": #{$font-size},
  "body": #{$body},
  "fs-xl": #{$fs-xl},
  "fs-lg": #{$fs-lg},
  "fs-sm": #{$fs-sm},
  "fs-xs": #{$fs-xs},
  "fs-xxs": #{$fs-xxs},
  "h1": #{$h1},
  "h2": #{$h2},
  "h3": #{$h3},
  "h4": #{$h4},
  "h5": #{$h5},
  "h6": #{$h6},
  "lh-body": #{$lh-body},
  "lh-header": #{$lh-header},
) !default;

The typography styles can be customized in the _styles.scss document, they're written as standard CSS with limited Sass functionality included for compiling purposes.

Styles

As the contents below shows _styles.scss document also includes the buttons and forms and tables styles but they have not been included in the example below.

//  ------------------------------------------------------------
//  Styles
//   1. Resets 
//   2. Typography
//   3. Smooth scroll and view-transition (if enabled)
//   4. Accessibility (if enabled)
//   5. Forms and buttons (if enabled)
//   6. Tables (if enabled)
//  ------------------------------------------------------------
@use "../configuration" as *;
@use "../properties" as *;

//  ------------------------------------------------------------
//  1. Resets
//  ------------------------------------------------------------

* { 
  margin: 0;
}

*, *::before, *::after {
  box-sizing: border-box;
}

//  ------------------------------------------------------------
//  2. Typography
//  ------------------------------------------------------------

:where(html, body, h1, h2, h3, h4, h5, h6) {
  color: var(--color);
  font-size: var(--fs);
  font-weight: var(--fw);
  line-height: var(--lh);
}

:where(html) {
  color-scheme: light dark;
  font-family: var(--font);
  background-color: var(--body-bg);
  height: 100%;
}

:where(body) {
  --fs: var(--body);
  --fw: normal;
  --lh: var(--lh-body);
}

:where(a) {
  --color: var(--link);
  --hover: var(--link-hover);
  --visited: var(--link-visited);
  @if $enable-icon-mixins or $enable-icon-styles {
  --ico: var(--color);
  }
  color: var(--color);
  overflow-wrap: break-word;
  text-decoration-color: color-mix(in srgb, var(--color) 75%, var(--body-bg));
  text-decoration-thickness: 1px;
  text-underline-offset: .1175em;
}

:where(a:visited) {
  color: var(--visited);
  text-decoration-color: color-mix(in srgb, var(--link) 35%, var(--body-bg)); 
}

:where(a:hover) {
  @if $enable-icon-mixins or $enable-icon-styles {
  --ico: var(--hover);
  }
  color: var(--hover);
  text-decoration: none;
}

:where(a:focus-visible) {
  outline: .094rem solid var(--link-hover);
  outline-offset: .1175rem;
  border-radius: .15em;
}

:where(h1, h2, h3, h4, h5, h6) a {
  text-decoration: none;
}

:where(h1, h2, h3, h4, h5, h6, p, ol, ul, dl, address) {
  text-wrap: var(--tw);
  margin-block-end: var(--mb);
}

:where(h1, h2, h3, h4, h5, h6) {
  --fw: 700;
  --lh: var(--lh-header);
  --tw: pretty;
  --mb: .75rem;
}

:where(h1) {
  --fs: var(--h1);
}

:where(h2) {
  --fs: var(--h2);
}

:where(h3) {
  --fs: var(--h3);
}

:where(h4) {
  --fs: var(--h4);
}

:where(h5) {
  --fs: var(--h5);
}

:where(h6) {
  --fs: var(--h6);
  --lh: 1.25;
}

:where(small) {
  --fs: var(--fs-sm);
  font-size: var(--fs);
}

:where(h1, h2, h3, h4, h5, h6) small {
  --fs: .75em;
}

:where(bold, strong) {
  --fw: bold;
  font-weight: var(--fw);
}

:where(p, ol, ul, dl, address) {
  --tw: pretty;
  --mb: 1rem;
  line-height: var(--lh);
}

:where(ol, ul) {
  --pl: 2rem;
  padding-inline-start: var(--pl);
}

:where(ol) {
  list-style-type: var(--marker, decimal);
}

:where(ul) {
  list-style-type: var(--marker, disc);
}

:where(ol ol, ul ul, ol ul, ul ol, dl dl) {
  --mb: 0;
}

:where(dl) {
  --fw: bold;
  --dd-ml: 1rem;
}

:where(dt) {
  font-weight: var(--fw);
}

:where(dt):not(:first-child) {
  margin-block-start: var(--dt-mt);
}

:where(dd) {
  margin-inline-start: var(--dd-ml);
}

:where(abbr[title]) {
  border: none;
  cursor: help;
}

:where(sup, sub) {
  font-size: var(--fs-xxs);
}

:where(mark) {
  color: marktext;
}

:where(code) {
  color: color-mix(in srgb, var(--text) 60%, var(--body-bg));
  word-wrap: break-word;
}

a > :where(code) {
  color: inherit;
}

:where(pre, code, kbd, samp) {
  font-family: Consolas, SFMono-Regular, monospace;
}

:where(kbd) {
  padding-block: .1em;
  padding-inline: .35em;
  background-color: var(--surf-2);
  border-radius: .25rem;
}

:where(pre) {
  overflow: auto;
  border: 1px solid var(--surf-2);
  padding: 1rem;
  margin-block-end: 1rem;
}

:where(pre code) {
  color: revert;
  word-break: normal;
}

:where(address) {
  font-style: normal;
}

:where(blockquote) {
  border: 1px solid var(--surf-1);
  border-inline-start-width: 10px;
  padding-block: .75rem;
  padding-inline: 1rem;
  margin-block-end: 1rem;
}

:where(blockquote p) {
  --mb: 0;
}

:where(blockquote p:first-of-type) {
  --fs: var(--fs-lg);
  --mb: .25rem;
  font-size: var(--fs);
}

:where(details) {
  --fw: bold;
  --mb-open: 1rem;
  margin-block-end: 1rem;
}

:where(summary) {
  font-weight: var(--fw);
  cursor: pointer;
}

:where(details[open] summary) {
  margin-block-end: var(--mb-open);
}

:where(hr) {
  box-sizing: content-box;
  height: 0;
  overflow: visible;
  border: none;
  border-block-start: 1px solid var(--surf-2);
  margin-block-end: 1rem;
}

:where(figure) {
  margin: 0;
  margin-block-end: 1rem;
}

:where(figcaption) {
  font-size: var(--fs-xs);
  padding-block-start: .5rem;
}

:where(img, svg, video, audio, iframe, embed, object) {
  display: block;
}

:where(img, svg) { 
  max-width: 100%;
}

:where(iframe) {
  border: 0;
}

.hidden {
  display: none;
}


//  ------------------------------------------------------------
//  3. Smooth scroll and view-transition (if enabled)
//  ------------------------------------------------------------

@media (prefers-reduced-motion: no-preference) { 
  @if $enable-smooth-scroll {
    :where(html) {
      scroll-behavior: smooth;
    }
  }
  
  @if $enable-view-transition {
    @view-transition {
      navigation: auto;
    }
  }
}

//  ------------------------------------------------------------
//  4. Accessibility (if enabled)
//  ------------------------------------------------------------

@mixin vis-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip: rect(0,0,0,0);
  white-space: nowrap;
}

@mixin vis-hidden-focus {
  &:not(:focus):not(:focus-within) {
    @include vis-hidden;
  }
}

@if $enable-vis-hidden {
  .vis-hidden, .vis-hidden-focus:not(:focus):not(:focus-within) {
    @include vis-hidden;
  }
}