Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
a4b6627
Created folder from template 👯‍♂️
triplingual Jul 3, 2025
912f3c8
Moved entry to appropriate numerical order 🚚
triplingual Jul 3, 2025
e71ba76
Moved entry to appropriate numerical order 🚚
triplingual Jul 3, 2025
1ad28eb
Added entry for CSS recipe ➕
triplingual Jul 3, 2025
5a7d036
Added bare-bones external stylesheet for recipe purpose 🎨
triplingual Jul 29, 2025
80a8263
Added base image to show what rendering could look like WIP 🖼️🚧
triplingual Jul 29, 2025
3d72f3d
Made an initial draft of the recipe text 📝
triplingual Jul 29, 2025
7c0533b
Made a first draft of a correct manifest 📝
triplingual Jul 29, 2025
ecd40c1
Removed duplicative template tag for path 🚮
triplingual Jul 29, 2025
0f50d8f
Changed title to change focus 📝
triplingual Jul 29, 2025
1f73cd7
Refined second annotation, restored style to first 📝
triplingual Jul 29, 2025
39c96e5
Merge branch 'master' into 0045-css
triplingual Aug 5, 2025
c751f03
Conformed entries to recipe title change ♻️
triplingual Aug 5, 2025
8f4c384
Simulated annotation rendering ✨
triplingual Aug 5, 2025
a6503fe
Revised stylesheet for precision and relationship to recipe 🎨
triplingual Aug 5, 2025
8db1a44
Refined use case & text, added highlighting, removed viewers 📝
triplingual Aug 5, 2025
e539f7f
Fixed dimensions, made styleClass semantic, improved annotation authe…
triplingual Aug 5, 2025
de36ce0
Copyedited Use Case, Implementation, Restrictions 📝
triplingual Aug 18, 2025
de3d7fc
Added viewer, removed demo image, added stylesheet view 📝
triplingual Aug 18, 2025
1feee57
Removed since there's viewer support 🚮
triplingual Aug 18, 2025
c0530af
Merge branch 'master' into 0045-css
triplingual Aug 18, 2025
45ab6a8
Revised description of linked recipe (HTML in Annotations)
triplingual Aug 18, 2025
4a68f4b
Added recommendation to set CORS headers per @stephenwf 📝
triplingual Aug 18, 2025
9638397
Changed text color to acid green 🎨
triplingual Sep 10, 2025
4ada1fb
Added border color speculatively 🎨
triplingual Sep 10, 2025
7c02106
Added text around styling the target as well as the body 📝
triplingual Sep 10, 2025
99b9ec5
Refined text for clarity, aligned versions 📝
triplingual Sep 10, 2025
6d1e6dd
Pointed to correct manifest, added highlighting 🛠️🖍️
triplingual Sep 10, 2025
4d04908
Deepened text color for readability 🎨
triplingual Sep 10, 2025
30e92ad
Initial commit to version control ⚡️
triplingual Sep 10, 2025
eef51ba
Moved alt content to use this version 🚚
triplingual Sep 10, 2025
0644d86
Removed as no longer needed 🚮
triplingual Sep 10, 2025
d64f23e
Merge branch 'master' into 0045-css
glenrobson Sep 12, 2025
83107ca
Changed recipe title to reflect content 📝
triplingual Sep 17, 2025
4151b2a
Reworded use case to follow cookbook style 📝
triplingual Sep 17, 2025
5f29dac
[ungitlike big ball of changes; see extended commit message]
triplingual Sep 17, 2025
c8278f3
Added `type` property of SpecificResource to annotation targets ➕
triplingual Sep 17, 2025
2cc3594
Merge branch 'master' into 0045-css
glenrobson Sep 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions _includes/links.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,12 @@
[0009]: {{ site.cookbook_url | absolute_url }}/recipe/0009-book-1/ "Simple Manifest - Book"
[0010]: {{ site.cookbook_url | absolute_url }}/recipe/0010-book-2-viewing-direction "Viewing direction and its effect on navigation"
[0011]: {{ site.cookbook_url | absolute_url }}/recipe/0011-book-3-behavior/ "Book behavior (paging) variations"
[0299]: {{ site.cookbook_url | absolute_url }}/recipe/0299-region/ "Addressing a spatial region"
[0013]: {{ site.cookbook_url | absolute_url }}/recipe/0013-placeholderCanvas/ "Load a Preview Image Before the Main Content"
[0202]: {{ site.cookbook_url | absolute_url }}/recipe/0202-start-canvas/ "Load Manifest Beginning with a Specific Canvas"
[0014]: {{ site.cookbook_url | absolute_url }}/recipe/0014-accompanyingcanvas/ "Audio Presentation with Accompanying Image"
[0015]: {{ site.cookbook_url | absolute_url }}/recipe/0015-start/ "Begin playback at a specific point - Time-based media"
[0017]: {{ site.cookbook_url | absolute_url }}/recipe/0017-transcription-av/ "Providing Access to Transcript Files of A/V Content"

[0139]: {{ site.cookbook_url | absolute_url }}/recipe/0139-geolocate-canvas-fragment/ "Represent Canvas Fragment as a Geographic Area on a Web Map"

[0019]: {{ site.cookbook_url | absolute_url }}/recipe/0019-html-in-annotations/ "HTML in Annotations"
[0021]: {{ site.cookbook_url | absolute_url }}/recipe/0021-tagging/ "Simple Annotation — Tagging"
[0022]: {{ site.cookbook_url | absolute_url }}/recipe/0022-linking-with-a-hotspot/ "Redirecting from one Canvas to another resource (Hotspot linking)"
Expand All @@ -33,6 +30,7 @@
[0031]: {{ site.cookbook_url | absolute_url }}/recipe/0031-bound-multivolume/ "Multiple Volumes in a Single Bound Volume"

[0040]: {{ site.cookbook_url | absolute_url }}/recipe/0040-image-rotation-service/ "Image Rotation Two Ways"
[0045]: {{ site.cookbook_url | absolute_url }}/recipe/0045-css/ "CSS in an Annotation"

[0047]: {{ site.cookbook_url | absolute_url }}/recipe/0047-homepage/ "Linking to Web Page of an Object"
[0046]: {{ site.cookbook_url | absolute_url }}/recipe/0046-rendering/ "Providing Alternative Representations"
Expand All @@ -49,7 +47,7 @@
[0118]: {{ site.cookbook_url | absolute_url }}/recipe/0118-multivalue/ "Displaying Multiple Values with Language Maps"

[0135]: {{ site.cookbook_url | absolute_url }}/recipe/0135-annotating-point-in-canvas/ "Annotating a specific point of an image"

[0139]: {{ site.cookbook_url | absolute_url }}/recipe/0139-geolocate-canvas-fragment/ "Represent Canvas Fragment as a Geographic Area on a Web Map"
[0154]: {{ site.cookbook_url | absolute_url }}/recipe/0154-geo-extension/ "Locate a Manifest on a Web Map"

[0232]: {{ site.cookbook_url | absolute_url }}/recipe/0232-image-thumbnail-canvas/ "Implementation discussion: Thumbnails on Canvases"
Expand All @@ -66,6 +64,7 @@
[0266]: {{ site.cookbook_url | absolute_url }}/recipe/0266-full-canvas-annotation/ "Simplest Annotation"
[0269]: {{ site.cookbook_url | absolute_url }}/recipe/0269-embedded-or-referenced-annotations/ "Embedded or Referenced Annotations"
[0283]: {{ site.cookbook_url | absolute_url }}/recipe/0283-missing-image/ "Missing Images in a Sequence"
[0299]: {{ site.cookbook_url | absolute_url }}/recipe/0299-region/ "Addressing a spatial region"

[0306]: {{ site.cookbook_url | absolute_url }}/recipe/0306-linking-annotations-to-manifests/ "Linking external Annotations targeting a Canvas to a Manifest"
[0309]: {{ site.cookbook_url | absolute_url }}/recipe/0309-annotation-collection/ "Using Annotation Collections"
Expand Down
1 change: 1 addition & 0 deletions index.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ _(leading on to segmentation examples later)_
* comments - various examples (51,52,54)
* [Simplest Annotation][0266]
* [HTML in Annotations][0019]
* [CSS in an Annotation][0045]
* Fragment selectors (61)
* [Simple Annotation - Tagging][0021]
* [Annotation with a Non-Rectangular Polygon][0261]
Expand Down
2 changes: 1 addition & 1 deletion recipe/0019-html-in-annotations/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"type": "AnnotationPage",
"items": [
{
"id": "{{ id.path }}{{ id.path }}/canvas-1/annopage-2/anno-1",
"id": "{{ id.path }}/canvas-1/annopage-2/anno-1",
"type": "Annotation",
"motivation": "commenting",
"body": {
Expand Down
57 changes: 57 additions & 0 deletions recipe/0045-css/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
title: CSS in an Annotation
id: 45
layout: recipe
tags: [style]
summary: "Using an external CSS stylesheet in an annotation body, annotations can be styled in limited ways"
viewers:
- Theseus
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be:

  • id: Theseus
    support: partial

As it doesn't support the target styling.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The target styling is supported now on Theseus, but there is a CORS issue when loading the style.css file at the moment. https://theseusviewer.org/?iiif-content=https%3A%2F%2Fpreview.iiif.io%2Fcookbook%2F0045-css%2Frecipe%2F0045-css%2Fmanifest.json

topic:
- basic
code:
- iiif-prezi3
---

## Use Case

You have two different authors who have each made an annotation on a visual resource. You'd like to distinguish the authors visually in the presentation, putting each annotation text in a different text color.

## Implementation Notes

Using CSS in annotations is covered in the W3C Web Annotation Data Model. For a look at its approach to styles in Web Annotations, see [the W3C Web Annotation Data Model's Styles section](https://www.w3.org/TR/annotation-model/#styles). Note in particular changes needed to the `target` property if styling is intended for a IIIF Canvas.

Annotations can be styled using CSS in three ways. This recipe focuses on using an external stylesheet. To add CSS using an external stylesheet, insert the stylesheet's URI as the the value of a `stylesheet` property on the Annotation. The `styleClass` property can then be used to reference rules in that external stylesheet, such as in the annotation `body` or composite `target` containing a `source` as well. It is advisable to set appropriate CORS headers for the stylesheet to improve its chances of working in generic viewers.

Viewer behavior and the specifics of an annotation's `target` will have effects, but broadly speaking, using CSS to style the `body` of an annotation will style the content of the annotation and a CSS class in the `target` will style the annotation's highlight on a Canvas.

The two other methods for adding CSS to a manifest are inline CSS and an inline stylesheet. To see how to use an inline stylesheet, see [Image Rotation Two Ways][0040]. To see how to use inline CSS, see [Visible Text Resource on a Canvas][0561]. Each of these also shows styling a IIIF resource in an annotation with a `motivation` of `painting` — that is, styling content that can be expected to be visible in the content space of a viewer.

## Restrictions

See the Restrictions section of the [HTML in Annotations][0019] recipe for a brief discussion of limitations to markup in annotations. These limitations can affect, in turn, the possible selectors in your external stylesheet.

The CSS approach depends wholly on viewer implementation of CSS as applied to a resource. Viewers have no requirement to support CSS styling. Browser-based viewers may defer CSS implementation in whole or in part to the browser. Consequently, and also for reasons of accessibility, annotations should not rely on styling for semantics and should be readable by a human or machine without styling.

One example: Since IIIF Canvas dimensions are unit-less, using pixels for text size is valid but may be interpreted variably across viewers or other clients.

## Example

This recipe focuses on annotations with motivations other than painting and on an external CSS stylesheet. The Theseus viewer is included here for its support of styling the annotation text, but it does not currently support styling the `target`.

{% include manifest_links.html manifest="manifest.json" %}

{% include jsonviewer.html src="manifest.json" config='data-line="56,60,71,78,82,93"' %}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be:

"56,60,72,79,83,95"

As the highlighting is slightly off


### Stylesheet
{% include jsonviewer.html src="style.css" %}

## Related Recipes

* [Image Rotation Two Ways][0040], for an inline CSS stylesheet used with a IIIF resource
* [HTML in Annotations][0019], a complementary recipe for markup, including a fuller discussion of markup use cautions
* [Visible Text Resource on a Canvas][0561], for inline CSS used with a painted textual resource

{% include acronyms.md %}
{% include links.md %}


103 changes: 103 additions & 0 deletions recipe/0045-css/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
{
"@context": "http://iiif.io/api/presentation/3/context.json",
"id": "{{ id.url }}",
"type": "Manifest",
"label": {
"en": [
"Koto, chess, calligraphy, and painting"
],
"ja": [
"琴棋書画図屏風"
]
},
"items": [
{
"id": "{{ id.path }}/canvas/p1",
"type": "Canvas",
"height": 3966,
"width": 8800,
"items": [
{
"id": "{{ id.path }}/page/p1/1",
"type": "AnnotationPage",
"items": [
{
"id": "{{ id.path }}/annotation/p0001-image",
"type": "Annotation",
"motivation": "painting",
"body": {
"id": "https://iiif.io/api/image/3.0/example/reference/36ca0a3370db128ec984b33d71a1543d-100320001004/full/max/0/default.jpg",
"type": "Image",
"format": "image/jpeg",
"height": 3966,
"width": 8800,
"service": [
{
"id": "https://iiif.io/api/image/3.0/example/reference/36ca0a3370db128ec984b33d71a1543d-100320001004",
"profile": "level1",
"type": "ImageService3"
}
]
},
"target": "{{ id.path }}/canvas/p1"
}
]
}
],
"annotations": [
{
"id": "{{ id.path }}/page/p2/1",
"type": "AnnotationPage",
"items": [
{
"id": "{{ id.path }}/page/p2/anno-1",
"type": "Annotation",
"motivation": "commenting",
"stylesheet": "{{ id.path }}/style.css",
"body": {
"id": "{{ id.path }}/body/sr1",
"type": "SpecificResource",
"styleClass": "author1",
"source": {
"id": "{{ id.path }}/body/text1",
"type": "TextualBody",
"language": "en",
"format": "text/html",
"value": "<p>Three of the four pursuits of refined and noble men named in the screen's title are shown on this side of the screen: go, the koto, and tools for calligraphy. Each is in a container or wrapper. (GR)</p>"
}
},
"target": {
"type": "SpecificResource",
"source": "{{ id.path }}/canvas/p1#xywh=700,1250,1850,1150",
"styleClass": "author1"
}
},
{
"id": "{{ id.path }}/page/p2/anno-2",
"type": "Annotation",
"motivation": "commenting",
"stylesheet": "{{ id.path }}/style.css",
"body": {
"id": "{{ id.path }}/body/sr2",
"type": "SpecificResource",
"styleClass": "author2",
"source": {
"id": "{{ id.path }}/body/text2",
"type": "TextualBody",
"language": "en",
"format": "text/html",
"value": "<p>The detail in the natural beauty of the setting could be seen as a contrast (or balance) to the manufactured pursuits of noble men. (TK)</p>"
}
},
"target": {
"type": "SpecificResource",
"source": "{{ id.path }}/canvas/p1#xywh=170,160,2200,1000",
"styleClass": "author2"
}
Comment on lines +92 to +96
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if the source can itself be a specific resource.

I think this would be more expected for a "SpecificResource" class:

"target": {
  "type": "SpecificResource",
  "source": "https://preview.iiif.io/cookbook/0045-css/recipe/0045-css/canvas/p1",
  "styleClass": "author2",
  "selector": {"type": "FragmentSelector", "value": "xywh=170,160,2200,1000"}
}

}
]
}
]
}
]
}
11 changes: 11 additions & 0 deletions recipe/0045-css/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.author1 {
color: #f00;
background-color: #fff;
border-color: #f00;
}

.author2 {
color: #1a1;
background-color: #fff;
border-color: #0f0;
}
Loading