跳到內容

用 CSS 設定 HTML 樣式

本則 recipe(範例)會使用 inline style 屬性與一個 <style> 區塊,將 CSS 套用到 HTML 內容。它也會示範如何在你依賴某個屬性前,先確認它已通過驗證。

Terminal window
composer require nextpdf/core:^3

這個版本限制適用於 nextpdf/core 套件。這個範例在 PHP 8.4 上執行。

HTML 引擎會透過 CSS 階層(cascade)來 resolve(解析)樣式。階層是一組規則;當多條規則指向同一個元素時,它會決定哪個樣式勝出。引擎會先讀取輸入中的 <style> 區塊,再讀取 inline style 屬性。它會將兩者都與元素比對,並依階層順序計算結果。支援矩陣將 CSS Cascading and Inheritance(階層與繼承)模組評為「Verified(已驗證)」,表示階層與繼承行為有一套專屬的 fixture 測試套件支撐。

文字呈現屬性,例如 text-aligntext-indentletter-spacing,來自 CSS Text 模組的屬性表(W3C CSS Text Level 3)。字型選擇採用 CSS Fonts 模型。font 簡寫會一次設定 font-stylefont-variantfont-weightfont-sizefont-family(W3C CSS Fonts Level 3)。

支援狀態會依循各個 W3C 模組,並經過真實性稽核。已實作但沒有專屬模組 fixture 的屬性,會被評為「Claimed(已宣稱)」,而不是「Verified」。請將「Claimed」視為盡力而為,並針對你的內容驗證視覺結果。請將「Verified」視為有一套已通過的 fixture 測試套件支撐。

你會透過傳入 writeHtml(string $html): static 的 HTML 驅動所有樣式(NextPDF\Core\Concerns\HasTextOutput)。沒有獨立的 CSS API;階層會在內部執行。完整的 PHPDoc 表格由原始碼產生。

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->addPage();
$doc->writeHtml(
'<style>.lead { color: #1E3A8A; text-align: center; }</style>'
. '<p class="lead">Styled with a style block.</p>'
);
$doc->save(__DIR__ . '/out.pdf');

這個範例是自我包含的,可在 harness 中執行。它會演練一個 <style> 區塊、類別選擇器、inline 樣式,以及 font 字型家族與字重的處理路徑。

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->setTitle('CSS Styling');
$doc->addPage();
$html = <<<'HTML'
<style>
h1 { color: #1E3A8A; }
.lead { color: #D97706; font-size: 14px; }
.callout { background-color: #EFF6FF; padding: 8px; border: 1px solid #BFDBFE; }
.centered { text-align: center; }
</style>
<h1>Styling HTML with CSS</h1>
<p class="lead">This paragraph is styled through a class selector in a
style block.</p>
<p class="callout">This paragraph has a background, padding, and a border
from a class selector.</p>
<p class="centered" style="font-weight: bold;">Centered, with an inline
override for weight.</p>
<p style="color: #6B7280; font-size: 9px;">Inline style only.</p>
HTML;
$doc->writeHtml($html);
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');
$doc->save($out !== false ? $out : __DIR__ . '/style-with-css.pdf');
echo "Wrote style-with-css.pdf\n";

預期的 STDOUT:

Wrote style-with-css.pdf
  • 階層順序。 依照階層規則,inline style 會勝過具有相同特定性(specificity)的 <style> 區塊選擇器。如果你看到非預期的顏色,請先檢查是否有 inline 覆寫。
  • Claimed 與 Verified 的差別。 text-aligntext-indentcolor 在矩陣中評為「Claimed」。它們已實作,但沒有專屬的模組 fixture。雖然它們會繪製出來,但在正式環境簽核前,仍請驗證其視覺輸出。
  • 沒有保留樹狀結構。 串流引擎(ADR-001)不保留任何文件樹,因此它無法套用「由後續兄弟元素重新設定前面元素樣式」的選擇器。不依文件順序運作的選擇器會受到限制。
  • 不支援的屬性。 不支援的屬性會被忽略,而不會引發錯誤。在你依賴它之前,請先對照矩陣確認。
  • 色彩空間。 Lab、LCH 與 OKLab 值會被剖析,但尚未對這些函式的 PDF 色彩空間保真度提出斷言(矩陣中:CSS Color 4 為「Claimed」)。

階層解析是單一處理流程的一部分。其成本與 token 數量維持線性關係,即 O(n)。預算為 wall_ms: 1500, peak_mb: 96<style> 區塊會增加一次性的選擇器剖析成本,這個成本與規則數量成正比。

這份摘錄只重現經過真實性稽核的 Verified 列;這些列來自 CSS 支援矩陣

W3C 模組層級狀態證據
CSS Cascading and Inheritance 階層與繼承(css_cascade_33已驗證src/Html/Cascade/tests/Unit/Html/Cascade/
CSS Cascading 階層(css_cascade_44已驗證Cascade/Layer/ 加上 revert/layer 測試
CSS Cascading 階層(css_cascade_55已驗證AtRule/Layer/ 加上 Cascade/Layer/ 測試套件
CSS Fonts 字型(css_fonts_33已驗證src/Html/Font/tests/Unit/Font/ 加上 FontResolver 測試
CSS Fonts 字型(css_fonts_44已驗證src/Html/FontFace/tests/Unit/Html/FontFace/

text-aligntext-indentcolorbackground-color 在矩陣中為「Claimed」。本表刻意把它們排除在 Verified 列之外。

階層會在一份串流 token 清單上執行,沒有 DOM;因此,選擇器會依文件順序的上下文解析。整棵樹狀結構的選擇器情境受 ADR-006 限制。請撰寫只依賴文件順序與祖先上下文的 CSS。

CSS 剖析屬於階層層,版面配置分派不得直接讀取原始的 $css[...] 值。對外公開的介面是 HTML 輸入。沒有任何受支援的方式可以繞過階層,注入已運算的樣式。

階層會保留目前作用中的規則集,以及推入與彈出的樣式堆疊,而不是節點樹。容器範圍的上下文會遵守 ADR-020 的預算(每個上下文 5,000 個節點,作用中記憶體上限 50 MB)。大型樣式表會使規則集記憶體呈線性增加,因此請將選擇器數量控制在有限範圍內。

不受信任 HTML 中的 CSS 無法執行程式碼,但能影響版面配置與資源參照(例如 background-image)。預設的外部資源政策不會擷取任意遠端 URL。在繪製之前,請先清理任何由使用者輸入組成的 HTML 與 CSS。

陳述規範條款參考 ID(reference_id)
文字屬性(text-align、text-indent、letter-spacing)由 CSS Text 屬性表定義。W3C CSS Text Level 3(文字模組)css_text_3#x1.x24(條款)
font 簡寫會設定 font-style、font-variant、font-weight、font-size 與 font-family。W3C CSS Fonts Level 3(字型模組)css_fonts_3#x2.x6.x7.p2(條款)

這則 recipe 示範 NextPDF 如何套用受支援的 CSS 子集;並未主張支援完整的 CSS。如需各模組經驗證的支援狀態,請參閱 CSS 支援矩陣。

不適用。