ARTLUNG LAB Share

Created Jul 2025

Comics Accessibility [DRAFT IN PROGRESS]

I started this page during Front End Study Hall #032.

The goal is to collect examples of different techniques for adding transcripts, scripts, alt text, etc to allow for accessible comics for users with different abilities.

If you'd like to contribute an example please reach out! Comments and webmentions are enabled. And you can also find me on Bluesky and Mastodon via my links page. Also there's a GitHub link in the footer which is another way to contribute.

Copyrights for the comics shown here are held by their respective authors.

Example from Joe

This example uses aria-describedby to point at markup that describes the comic. I believe I can set the div with the description to be hidden and have that work in screen readers but it needs further testing.

A web comic
Panel 1
Image of a swimmer standing on a beach, turned away from viewer, carrying swim fins
Caption: Sunday bodysurfing session done. I pause to appreciate the quiet beauty of...
Panel 2
Image of a something falling to the sand with a "THUD!"sound effect. The swimmer exclaims "yikes!" and jumps away.
Panel 3a:
Closeup image of a clam, with a crack in it,
Panel 3b:
Swimmer has a mobile phone out taking a photo of the clam
Thought bubble: "A clam?!"
Panel 4a:
Image of a seagull flying downward, mouth open with the sound effect "SWOOP"
Panel 4b:
Image of the seagul tearing into the broken clam extracting meat
Seagull exclaims "My clam!" The word "My" is emphasized.
Panel 4c
Closeup image of the swimmer's surprised face
Caption: "ok then!:
End of comic, signature reads "ARTLUNG"
Sources

HTML

<div class="comic-image">
<img fetchpriority="high" decoding="async"
     src="https://cdn.artlung.com/blog/wp-content/uploads/2022/08/drop-it-like-its-bivalve-scaled.jpg"
     alt="A web comic" width="2560" height="2560"
     srcset="https://cdn.artlung.com/blog/wp-content/uploads/2022/08/drop-it-like-its-bivalve-scaled.jpg 2560w,
     https://cdn.artlung.com/blog/wp-content/uploads/2022/08/drop-it-like-its-bivalve-800x800.jpg 800w,
      https://cdn.artlung.com/blog/wp-content/uploads/2022/08/drop-it-like-its-bivalve-2048x2048.jpg 2048w,
       https://cdn.artlung.com/blog/wp-content/uploads/2022/08/drop-it-like-its-bivalve-100x100@2x.jpg 200w,
        https://cdn.artlung.com/blog/wp-content/uploads/2022/08/drop-it-like-its-bivalve-768x768.jpg 768w,
         https://cdn.artlung.com/blog/wp-content/uploads/2022/08/drop-it-like-its-bivalve-1536x1536.jpg 1536w,
          https://cdn.artlung.com/blog/wp-content/uploads/2022/08/drop-it-like-its-bivalve-100x100.jpg 100w,
           https://cdn.artlung.com/blog/wp-content/uploads/2022/08/drop-it-like-its-bivalve-800x800@2x.jpg 1600w,
            https://cdn.artlung.com/blog/wp-content/uploads/2022/08/drop-it-like-its-bivalve-200x200@2x.jpg 400w"
     sizes="(max-width: 2560px) 100vw, 2560px"
    aria-describedby="drop-it-text-version"
>
</div>
<div id="drop-it-text-version">
    <dl>
        <dt>
            Panel 1
        </dt>
        <dd>
            Image of a swimmer standing on a beach, turned
            away from viewer, carrying swim fins
        </dd>
        <dd>
            Caption: Sunday bodysurfing session done. I pause
            to appreciate the quiet beauty of...
        </dd>
        <dt>
            Panel 2
        </dt>
        <dd>
            Image of a something falling to the sand with
            a "THUD!"sound effect. The swimmer exclaims
            "yikes!" and jumps away.
        </dd>
        <dt>
            Panel 3a:
        </dt>
        <dd>
            Closeup image of a clam, with a crack in it,
        </dd>
        <dt>
            Panel 3b:
        </dt>
        <dd>
            Swimmer has a mobile phone out taking a photo of
            the clam
        </dd>
        <dd>
            Thought bubble: "A clam?!"
        </dd>
        <dt>
            Panel 4a:
        </dt>
        <dd>
            Image of a seagull flying downward, mouth open
            with the sound effect "SWOOP"
        </dd>
        <dt>
            Panel 4b:
        </dt>
        <dd>
            Image of the seagul tearing into the broken
            clam extracting meat
        </dd>
        <dd>
            Seagull exclaims "My clam!"
            The word "My" is emphasized.
        </dd>
        <dt>Panel 4c</dt>
        <dd>
            Closeup image of the swimmer's surprised face
        </dd>
        <dd>
            Caption: "ok then!:
        </dd>
        <dd>
            End of comic, signature reads "ARTLUNG"
        </dd>
    </dl>
</div>

SCSS

.comic-image {
  width: 100%;
  max-width: 650px;
  height: auto;
  margin: 0;
  border-block-start: 1ch solid;
  img {
    display: block;
    width: 100%;
    height: auto;
  }

}

details {
  summary {
    font-size: 2rem;
    cursor: pointer;
  }
}

section {
  margin: 5rem 0;
  box-shadow: 0 0 0.4ch;
  padding: 2ch;
  > h2:first-child {
    margin-block-start: 0;
  }
  &.example-benji {
    @import 'example-benji';
  }
  &.example-tantek {
    @import 'example-tantek';
  }
  &.example-jamesg {
    @import 'example-jamesg';
  }
}

Example from Benji

This comic allows the user to toggle the display of descriptions which are initially hidden as paragraphs within each individual div element.

See CodePen

Description of panel 1
Description of panel 2
Description of panel 3
Description of panel 4
Sources

HTML

<label for="show-alt">Show alt text</label>
<input id="show-alt" type="checkbox">
<article>
    <figure>
        <img src="https://placekeanu.com/400/400" aria-labelledby="caption1">
        <figcaption id="caption1">Description of panel 1</figcaption>
    </figure>
    <figure>
        <img src="https://placekeanu.com/410/410" aria-labelledby="caption2">
        <figcaption id="caption2">Description of panel 2</figcaption>
    </figure>
    <figure>
        <img src="https://placekeanu.com/420/420">
        <figcaption>Description of panel 3</figcaption>
    </figure>
    <figure>
        <img src="https://placekeanu.com/430/430">
        <figcaption>Description of panel 4</figcaption>
    </figure>
</article>

SCSS

& {
  font-family: Avenir, Montserrat, Corbel, 'URW Gothic', source-sans-pro, sans-serif;
  font-weight: normal;
}
#show-alt:checked + article {
  grid-template-columns: 1fr;
  figure { grid-template-columns: 1fr 1fr }
  figcaption { display: block }
  gap: .5em;
}
article {
  display: grid;
  grid-template-columns: 1fr 1fr;
  max-width: 500px;
  gap: 0;
  figure {
    margin: 0;
    display: grid;
    grid-template-columns: 1fr;
  }
  figcaption {
    display: none;
    border: 1px solid black;
    padding: .5em;
  }
  img { width: 100% }
}

Example from Tantek Çelik

Bayesian

Picture a comic with four panels, featuring the same scene in each. There's a dialog between a woman with a ponytail reclining on a couch reading a book, and a man sitting on a rolling office chair, working at a desk with keyboard and upright flatscreen computer. Sunlight is streaming into the room through a closed double-hung window. Dialog commences, each line in its own panel, connected with a curved segment to the speaker, starting with the man and alternating:

“So sunny outside. Let's go for a walk.”

“It's so sunny, but it's only 18 degrees! [Celsius]”

“We could hold hands, would that help?”

“Probably. :)”

Dated and signed TÇ

This comic uses aria-label to provide a description of the comic. and uses an object tag to enclose the comic image and the fallback text.

See Bayesian Comic

Sources

HTML

<object type="image/jpeg" aria-labelledby="comic-text"
        title="Naturally she's using metric Celsius temperature units.
        Any resemblance to real dialog is purely coincidental.
        Txt messages on the other hand."
        data="https://farm8.staticflickr.com/7418/8885079426_2067278966_c.jpg">
    <div class="text-description" style="text-align:left" id="comic-text">
        <h1 class="p-name entry-title">Bayesian</h1>
        <p>Picture a comic with four panels, featuring the same scene
            in each. There's a dialog between a woman with a ponytail
            reclining on a couch reading a book, and a man sitting on
            a rolling office chair, working at a desk with keyboard
            and upright flatscreen computer. Sunlight is streaming
            into the room through a closed double-hung window.
            Dialog commences, each line in its own panel, connected
            with a curved segment to the speaker, starting with the
            man and alternating:
        </p>
        <p>“So sunny outside. Let's go for a walk.”</p>
        <p>“It's so sunny, but it's only 18 degrees! [Celsius]”</p>
        <p>“We could hold hands, would that help?”</p>
        <p>“Probably. :)”</p>
        <p>Dated <time datetime="2013-05-29">2013-149</time> and signed <abbr title="Tantek &#xC7;elik">TÇ</abbr></p>
    </div>
</object>

Example from James

This is markup and CSS with an included label and checkbox to toggle visibility of a separate div with a description.

See Alt Text

Fernande with a Black Mantilla, one of my favourite paintings
Fernande with a Black Mantilla
Sources

HTML

<figure>
    <div class="alt-parent alt">
        <label for="alt-item" id="label">
            <input type="checkbox" id="alt-item" class="alt-item" />Alt</label>
        <div class="content">Fernande with a Black Mantilla, one of my favourite paintings</div>
    </div>
    <img alt="Fernande with a Black Mantilla"
         src="https://www.guggenheim.org/wp-content/uploads/1905/01/91.3914_ph_web-1.jpg">
</figure>

SCSS

label, .content {
  position: absolute;
  font-family: Helvetica, sans-serif;
  top: 0.5rem;
  right: 0.5rem;
  background-color: white;
  color: black;
  border-radius: 0.25rem;
  padding: 0.2rem;
  padding-bottom: 0.1rem;
  padding-top: 0.1rem;
  box-shadow: 1px 1px 1px lightgrey;
  cursor: pointer;
  left: 0.5rem;
  max-width: fit-content;
  opacity: 1;
}
* {
  line-height: 1.5;
}
figure {
  max-width: 20rem;
  position: relative;
}
.content {
  display: none;
  max-width: 100%;
  left: 2.5rem;
}
.alt:has(input[type="checkbox"]:checked) > .content {
  display: block;
}
.alt:has(input[type="checkbox"]:focus) label {
  outline: yellow 1px solid;
  background-color: black;
  color: yellow
}
input[type="checkbox"]:focus {
  outline: none;
}
label {
  cursor: pointer;
}
input {
  height: 0.001px;
  width: 0.001px;
  margin-left: -0.1rem;
}
img {
  max-width: 100%;
}