diff --git a/quartz/components/ArticleTitle.tsx b/quartz/components/ArticleTitle.tsx
index a52b2a4..2484c94 100644
--- a/quartz/components/ArticleTitle.tsx
+++ b/quartz/components/ArticleTitle.tsx
@@ -1,9 +1,10 @@
 import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
+import { classNames } from "../util/lang"
 
 function ArticleTitle({ fileData, displayClass }: QuartzComponentProps) {
   const title = fileData.frontmatter?.title
   if (title) {
-    return <h1 class={`article-title ${displayClass ?? ""}`}>{title}</h1>
+    return <h1 class={classNames(displayClass, "article-title")}>{title}</h1>
   } else {
     return null
   }
diff --git a/quartz/components/Backlinks.tsx b/quartz/components/Backlinks.tsx
index c4172ce..d5bdc0b 100644
--- a/quartz/components/Backlinks.tsx
+++ b/quartz/components/Backlinks.tsx
@@ -1,12 +1,13 @@
 import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
 import style from "./styles/backlinks.scss"
 import { resolveRelative, simplifySlug } from "../util/path"
+import { classNames } from "../util/lang"
 
 function Backlinks({ fileData, allFiles, displayClass }: QuartzComponentProps) {
   const slug = simplifySlug(fileData.slug!)
   const backlinkFiles = allFiles.filter((file) => file.links?.includes(slug))
   return (
-    <div class={`backlinks ${displayClass ?? ""}`}>
+    <div class={classNames(displayClass, "backlinks")}>
       <h3>Backlinks</h3>
       <ul class="overflow">
         {backlinkFiles.length > 0 ? (
diff --git a/quartz/components/Breadcrumbs.tsx b/quartz/components/Breadcrumbs.tsx
index 182d9d6..3875f5e 100644
--- a/quartz/components/Breadcrumbs.tsx
+++ b/quartz/components/Breadcrumbs.tsx
@@ -2,6 +2,7 @@ import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
 import breadcrumbsStyle from "./styles/breadcrumbs.scss"
 import { FullSlug, SimpleSlug, resolveRelative } from "../util/path"
 import { QuartzPluginData } from "../plugins/vfile"
+import { classNames } from "../util/lang"
 
 type CrumbData = {
   displayName: string
@@ -113,7 +114,7 @@ export default ((opts?: Partial<BreadcrumbOptions>) => {
     }
 
     return (
-      <nav class={`breadcrumb-container ${displayClass ?? ""}`} aria-label="breadcrumbs">
+      <nav class={classNames(displayClass, "breadcrumb-container")} aria-label="breadcrumbs">
         {crumbs.map((crumb, index) => (
           <div class="breadcrumb-element">
             <a href={crumb.path}>{crumb.displayName}</a>
diff --git a/quartz/components/ContentMeta.tsx b/quartz/components/ContentMeta.tsx
index 5337fee..6cd083e 100644
--- a/quartz/components/ContentMeta.tsx
+++ b/quartz/components/ContentMeta.tsx
@@ -1,6 +1,7 @@
 import { formatDate, getDate } from "./Date"
 import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
 import readingTime from "reading-time"
+import { classNames } from "../util/lang"
 
 interface ContentMetaOptions {
   /**
@@ -33,7 +34,7 @@ export default ((opts?: Partial<ContentMetaOptions>) => {
         segments.push(timeTaken)
       }
 
-      return <p class={`content-meta ${displayClass ?? ""}`}>{segments.join(", ")}</p>
+      return <p class={classNames(displayClass, "content-meta")}>{segments.join(", ")}</p>
     } else {
       return null
     }
diff --git a/quartz/components/Darkmode.tsx b/quartz/components/Darkmode.tsx
index f1a7d08..6d10bb9 100644
--- a/quartz/components/Darkmode.tsx
+++ b/quartz/components/Darkmode.tsx
@@ -4,10 +4,11 @@
 import darkmodeScript from "./scripts/darkmode.inline"
 import styles from "./styles/darkmode.scss"
 import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
+import { classNames } from "../util/lang"
 
 function Darkmode({ displayClass }: QuartzComponentProps) {
   return (
-    <div class={`darkmode ${displayClass ?? ""}`}>
+    <div class={classNames(displayClass, "darkmode")}>
       <input class="toggle" id="darkmode-toggle" type="checkbox" tabIndex={-1} />
       <label id="toggle-label-light" for="darkmode-toggle" tabIndex={-1}>
         <svg
diff --git a/quartz/components/Explorer.tsx b/quartz/components/Explorer.tsx
index fdfff23..e964c5a 100644
--- a/quartz/components/Explorer.tsx
+++ b/quartz/components/Explorer.tsx
@@ -5,6 +5,7 @@ import explorerStyle from "./styles/explorer.scss"
 import script from "./scripts/explorer.inline"
 import { ExplorerNode, FileNode, Options } from "./ExplorerNode"
 import { QuartzPluginData } from "../plugins/vfile"
+import { classNames } from "../util/lang"
 
 // Options interface defined in `ExplorerNode` to avoid circular dependency
 const defaultOptions = {
@@ -77,7 +78,7 @@ export default ((userOpts?: Partial<Options>) => {
   function Explorer({ allFiles, displayClass, fileData }: QuartzComponentProps) {
     constructFileTree(allFiles)
     return (
-      <div class={`explorer ${displayClass ?? ""}`}>
+      <div class={classNames(displayClass, "explorer")}>
         <button
           type="button"
           id="explorer"
diff --git a/quartz/components/Graph.tsx b/quartz/components/Graph.tsx
index 0c2647f..756a46b 100644
--- a/quartz/components/Graph.tsx
+++ b/quartz/components/Graph.tsx
@@ -2,6 +2,7 @@ import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
 // @ts-ignore
 import script from "./scripts/graph.inline"
 import style from "./styles/graph.scss"
+import { classNames } from "../util/lang"
 
 export interface D3Config {
   drag: boolean
@@ -56,7 +57,7 @@ export default ((opts?: GraphOptions) => {
     const localGraph = { ...defaultOptions.localGraph, ...opts?.localGraph }
     const globalGraph = { ...defaultOptions.globalGraph, ...opts?.globalGraph }
     return (
-      <div class={`graph ${displayClass ?? ""}`}>
+      <div class={classNames(displayClass, "graph")}>
         <h3>Graph View</h3>
         <div class="graph-outer">
           <div id="graph-container" data-cfg={JSON.stringify(localGraph)}></div>
diff --git a/quartz/components/PageTitle.tsx b/quartz/components/PageTitle.tsx
index 81d80d1..fb1660a 100644
--- a/quartz/components/PageTitle.tsx
+++ b/quartz/components/PageTitle.tsx
@@ -1,11 +1,12 @@
 import { pathToRoot } from "../util/path"
 import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
+import { classNames } from "../util/lang"
 
 function PageTitle({ fileData, cfg, displayClass }: QuartzComponentProps) {
   const title = cfg?.pageTitle ?? "Untitled Quartz"
   const baseDir = pathToRoot(fileData.slug!)
   return (
-    <h1 class={`page-title ${displayClass ?? ""}`}>
+    <h1 class={classNames(displayClass, "page-title")}>
       <a href={baseDir}>{title}</a>
     </h1>
   )
diff --git a/quartz/components/RecentNotes.tsx b/quartz/components/RecentNotes.tsx
index 9a53ad7..81b354d 100644
--- a/quartz/components/RecentNotes.tsx
+++ b/quartz/components/RecentNotes.tsx
@@ -5,6 +5,7 @@ import { byDateAndAlphabetical } from "./PageList"
 import style from "./styles/recentNotes.scss"
 import { Date, getDate } from "./Date"
 import { GlobalConfiguration } from "../cfg"
+import { classNames } from "../util/lang"
 
 interface Options {
   title: string
@@ -28,7 +29,7 @@ export default ((userOpts?: Partial<Options>) => {
     const pages = allFiles.filter(opts.filter).sort(opts.sort)
     const remaining = Math.max(0, pages.length - opts.limit)
     return (
-      <div class={`recent-notes ${displayClass ?? ""}`}>
+      <div class={classNames(displayClass, "recent-notes")}>
         <h3>{opts.title}</h3>
         <ul class="recent-ul">
           {pages.slice(0, opts.limit).map((page) => {
diff --git a/quartz/components/Search.tsx b/quartz/components/Search.tsx
index 9c1852d..92684ae 100644
--- a/quartz/components/Search.tsx
+++ b/quartz/components/Search.tsx
@@ -2,11 +2,12 @@ import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
 import style from "./styles/search.scss"
 // @ts-ignore
 import script from "./scripts/search.inline"
+import { classNames } from "../util/lang"
 
 export default (() => {
   function Search({ displayClass }: QuartzComponentProps) {
     return (
-      <div class={`search ${displayClass ?? ""}`}>
+      <div class={classNames(displayClass, "search")}>
         <div id="search-icon">
           <p>Search</p>
           <div></div>
diff --git a/quartz/components/Spacer.tsx b/quartz/components/Spacer.tsx
index 8359111..5288752 100644
--- a/quartz/components/Spacer.tsx
+++ b/quartz/components/Spacer.tsx
@@ -1,7 +1,8 @@
 import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
+import { classNames } from "../util/lang"
 
 function Spacer({ displayClass }: QuartzComponentProps) {
-  return <div class={`spacer ${displayClass ?? ""}`}></div>
+  return <div class={classNames(displayClass, "spacer")}></div>
 }
 
 export default (() => Spacer) satisfies QuartzComponentConstructor
diff --git a/quartz/components/TableOfContents.tsx b/quartz/components/TableOfContents.tsx
index 1c55f07..167c837 100644
--- a/quartz/components/TableOfContents.tsx
+++ b/quartz/components/TableOfContents.tsx
@@ -1,6 +1,7 @@
 import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
 import legacyStyle from "./styles/legacyToc.scss"
 import modernStyle from "./styles/toc.scss"
+import { classNames } from "../util/lang"
 
 // @ts-ignore
 import script from "./scripts/toc.inline"
@@ -19,7 +20,7 @@ function TableOfContents({ fileData, displayClass }: QuartzComponentProps) {
   }
 
   return (
-    <div class={`toc ${displayClass ?? ""}`}>
+    <div class={classNames(displayClass, "toc")}>
       <button type="button" id="toc" class={fileData.collapseToc ? "collapsed" : ""}>
         <h3>Table of Contents</h3>
         <svg
diff --git a/quartz/components/TagList.tsx b/quartz/components/TagList.tsx
index b39b199..e5dd1a3 100644
--- a/quartz/components/TagList.tsx
+++ b/quartz/components/TagList.tsx
@@ -1,12 +1,13 @@
 import { pathToRoot, slugTag } from "../util/path"
 import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
+import { classNames } from "../util/lang"
 
 function TagList({ fileData, displayClass }: QuartzComponentProps) {
   const tags = fileData.frontmatter?.tags
   const baseDir = pathToRoot(fileData.slug!)
   if (tags && tags.length > 0) {
     return (
-      <ul class={`tags ${displayClass ?? ""}`}>
+      <ul class={classNames(displayClass, "tags")}>
         {tags.map((tag) => {
           const display = `#${tag}`
           const linkDest = baseDir + `/tags/${slugTag(tag)}`
diff --git a/quartz/util/lang.ts b/quartz/util/lang.ts
index 5211b5d..31e8c02 100644
--- a/quartz/util/lang.ts
+++ b/quartz/util/lang.ts
@@ -9,3 +9,13 @@ export function pluralize(count: number, s: string): string {
 export function capitalize(s: string): string {
   return s.substring(0, 1).toUpperCase() + s.substring(1)
 }
+
+export function classNames(
+  displayClass?: "mobile-only" | "desktop-only",
+  ...classes: string[]
+): string {
+  if (displayClass) {
+    classes.push(displayClass)
+  }
+  return classes.join(" ")
+}