diff --git a/crates/doc/src/lib.rs b/crates/doc/src/lib.rs
--- a/crates/doc/src/lib.rs
+++ b/crates/doc/src/lib.rs
@@ -472,8 +472,9 @@ pub struct Artboard {
     pub video_ruler_pixel_aspect_ratio: f64,
     /// Background color (Properties › Artboards › Fill, Artboard Options). The canvas draws the
     /// artboard's paper in it, multiplied with the Simulate Colored Paper color while that is on;
-    /// without one the paper is white, or the Simulate Colored Paper color. Exports and print leave
-    /// it out.
+    /// without one the paper is white, or the Simulate Colored Paper color. PDF export and
+    /// single-artboard SVG export write it as a background behind the art; print and other exports
+    /// still omit it.
     #[serde(default, skip_serializing_if = "Option::is_none")]
     pub color: Option<vectorcraft_color::Color>,
 }
diff --git a/crates/pdf/src/export.rs b/crates/pdf/src/export.rs
--- a/crates/pdf/src/export.rs
+++ b/crates/pdf/src/export.rs
@@ -136,6 +136,7 @@ fn export_with_report_inner(doc: &Document, opts: &PdfOptions, left_out: &mut Ha
             clip: m != r,
             marks: art.as_ref(),
             negative: false,
+            background: doc.artboards.get(i).and_then(|a| a.color),
         };
         w.page(&mut ex, &sheet).map_err(|_| PdfError::BadArtboard(i))?;
     }
@@ -273,6 +274,8 @@ pub(crate) struct Sheet<'a> {
     pub marks: Option<&'a Node>,
     /// Invert the page: paper black, ink clear (a film negative).
     pub negative: bool,
+    /// Artboard background (Properties › Artboards › Fill), drawn behind the art on the trim box.
+    pub background: Option<Color>,
 }
 
 impl Writer {
@@ -350,6 +353,14 @@ impl Writer {
         // A page whose art or marks would be placed beyond [`MAX_COORD`] is left blank.
         let fits = writable(&s, sheet.view, Rect::ZERO) && writable(&s, sheet.view * sheet.place, Rect::ZERO);
         s.push_transform(&xf(sheet.view));
+        if fits && let Some(c) = sheet.background {
+            if let Some(p) = to_path(&s, &sheet.trim.to_path(0.1)) {
+                s.set_stroke(None);
+                s.set_fill(Some(Fill { paint: ex.col(&c).into(), opacity: NormalizedF32::ONE, rule: krilla::paint::FillRule::NonZero }));
+                s.draw_path(&p);
+            }
+            s.set_fill(None);
+        }
         let window = sheet.window.and_then(|r| to_path(&s, &r.to_path(0.1)));
         if let Some(clip) = &window {
             s.push_clip_path(clip, &krilla::paint::FillRule::NonZero);
diff --git a/crates/pdf/src/print/mod.rs b/crates/pdf/src/print/mod.rs
--- a/crates/pdf/src/print/mod.rs
+++ b/crates/pdf/src/print/mod.rs
@@ -338,6 +338,7 @@ impl PlannedSheet {
             clip: true,
             marks: self.marks.as_ref(),
             negative: self.negative,
+            background: None,
         }
     }
 }
diff --git a/crates/pdf/src/tests.rs b/crates/pdf/src/tests.rs
--- a/crates/pdf/src/tests.rs
+++ b/crates/pdf/src/tests.rs
@@ -68,6 +68,14 @@ fn export_is_valid_pdf() {
     assert_eq!(page_count(&bytes), 1);
 }
 
+#[test]
+fn artboard_background_color_is_drawn_on_pdf_export() {
+    let mut d = doc(200.0, 150.0);
+    d.artboards[0].color = Some(Color::from_hex("#336699").unwrap());
+    let plain = uncompressed(&d);
+    assert!(plain.contains("0.2 0.4 0.6 rg") || plain.contains("0.2 0.4 0.6 RG"), "{plain}");
+}
+
 #[test]
 fn metadata_creator_and_title() {
     let mut d = doc(100.0, 100.0);
