

<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>css &#8211; Max的程式語言筆記</title>
	<atom:link href="https://stackoverflow.max-everyday.com/tag/css/feed/" rel="self" type="application/rss+xml" />
	<link>https://stackoverflow.max-everyday.com</link>
	<description>我要當一個豬頭，快樂過每一天</description>
	<lastBuildDate>Mon, 26 Oct 2026 21:23:14 +0000</lastBuildDate>
	<language>zh-TW</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.4</generator>

<image>
	<url>https://stackoverflow.max-everyday.com/wp-content/uploads/2017/02/max-stackoverflow-256.png</url>
	<title>css &#8211; Max的程式語言筆記</title>
	<link>https://stackoverflow.max-everyday.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>SVG 動畫的排版小陷阱：讓線條和箭頭同步出現</title>
		<link>https://stackoverflow.max-everyday.com/2026/10/svg-path-marker-end/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/10/svg-path-marker-end/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Mon, 26 Oct 2026 21:21:44 +0000</pubDate>
				<category><![CDATA[css筆記]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[Debug]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=8830</guid>

					<description><![CDATA[最近在處理 SVG 動畫時，遇到了一個有趣的畫面...]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="572" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/10/watermarked_img_7311881495471058215_clean-1024x572.jpg?v=1793049781" alt="" class="wp-image-8833" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/10/watermarked_img_7311881495471058215_clean-1024x572.jpg?v=1793049781 1024w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/10/watermarked_img_7311881495471058215_clean-600x335.jpg?v=1793049781 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/10/watermarked_img_7311881495471058215_clean-767x428.jpg?v=1793049781 767w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/10/watermarked_img_7311881495471058215_clean.jpg?v=1793049781 1376w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">最近在處理 SVG 動畫時，遇到了一個有趣的畫面瑕疵。當我們使用 path 標籤搭配 marker-end 來加上箭頭時，瀏覽器展現動畫的行為跟我們預期的有點落差。</p>



<p class="wp-block-paragraph">這篇文章來記錄這個問題的根本原因，以及如何透過簡單的技巧完美解決。</p>



<h2 class="wp-block-heading">問題是甚麼</h2>



<p class="wp-block-paragraph">在網頁中，如果我們寫了 path 結合 marker-end 這樣的語法，本意是希望路徑在畫完的時候，終點才出現這個箭頭。</p>



<p class="wp-block-paragraph">但是實際執行動畫時，只要路徑開始顯現，也就是透明度變成 1 的那一個瞬間，瀏覽器就會在終點立刻把這個箭頭渲染出來。</p>



<p class="wp-block-paragraph">這會導致一個很不協調的現象：線條還在慢慢從起點畫過來，但終點已經提早立好了一個箭頭。</p>



<h2 class="wp-block-heading">為什麼會這樣</h2>



<p class="wp-block-paragraph">這是因為 SVG 的 marker-end 本質上就是一個綁定在路徑端點上的裝飾元件。</p>



<p class="wp-block-paragraph">當我們使用 stroke-dashoffset 來控制線條慢慢畫出來時，路徑只要一有顯示的跡象，瀏覽器就會認為端點已經存在，於是提前把裝飾的箭頭畫上去，沒有辦法隨著線條進度同步延遲出現。</p>



<h2 class="wp-block-heading">解決方案</h2>



<p class="wp-block-paragraph">為了讓箭頭配合線條畫到的時間點才出現，我們需要分開處理路徑和箭頭。</p>



<p class="wp-block-paragraph">第一步是移除 SVG 的 marker-end 屬性，這樣可以避免瀏覽器在路徑終點預先繪製箭頭。</p>



<p class="wp-block-paragraph">第二步是獨立一個箭頭元件出來，這裡使用 polygon 標籤來當作獨立的箭頭，並且根據路徑終點的座標以及切線斜率來旋轉對齊端點。</p>



<h2 class="wp-block-heading">程式碼實作</h2>



<p class="wp-block-paragraph">調整過後的程式碼像這樣：</p>



<p class="wp-block-paragraph">HTML</p>



<pre class="wp-block-code"><code>&lt;svg class="marathon-svg" viewBox="0 0 1400 260" xmlns="http://www.w3.org/2000/svg"&gt;
    &lt;!-- Track path --&gt;
    &lt;path id="track" d="M80,150 Q280,40 480,120 Q680,240 880,140 Q1080,50 1280,150 L1360,180" stroke="#C8922A" stroke-width="6" stroke-linecap="round" fill="none" stroke-dasharray="1360" stroke-dashoffset="1360" style="
            animation: dashDraw 3s ease forwards;
            --dash-len: 1360;
            animation-delay: calc(var(--scene-t,0s) * -1 + 9s);
            animation-play-state: paused;
            "&gt;&lt;/path&gt;
    &lt;!-- Arrowhead that appears when drawing reaches the end (at 11.5s) --&gt;
    &lt;polygon points="0 -9, 22 0, 0 9" fill="#C8922A" transform="translate(1360, 180) rotate(20.56)" style="
            opacity: 0;
            animation: fadeIn 0.3s ease forwards;
            animation-delay: calc(var(--scene-t,0s) * -1 + 11.5s);
            animation-play-state: paused;
            "&gt;&lt;/polygon&gt;
&lt;/svg&gt;
</code></pre>



<p class="wp-block-paragraph">透過把箭頭拉出來獨立控制，並且設定好對應的 animation-delay 讓它在時間點剛好對上線條畫完的一刻，就能解決箭頭提前出現的不協調感。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/10/svg-path-marker-end/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>如果 AI 生成的 Flex ：如何用 CSS Grid 打造完美的左右雙欄卡片</title>
		<link>https://stackoverflow.max-everyday.com/2026/10/css-from-flex-to-grid/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/10/css-from-flex-to-grid/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Tue, 20 Oct 2026 16:04:15 +0000</pubDate>
				<category><![CDATA[css筆記]]></category>
		<category><![CDATA[css]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=8815</guid>

					<description><![CDATA[在網頁前端開發中，我們經常需要將區塊拆分成左右兩...]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">在網頁前端開發中，我們經常需要將區塊拆分成左右兩欄，例如左邊放標籤或圖示、右邊放標題與內文。當我們把任務交給 AI 生成時，最常見的反應就是直接使用 Flexbox 排版。</p>



<p class="wp-block-paragraph">雖然 Flexbox 非常好用，但在處理多行、不規則高度或是希望呈現傳統表格對齊（例如類似 HTML 表格中的 tr 包含兩個 td ）的結構時，以下示範如何把第4列搬到第2例右側。</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="609" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/10/chrome_2026-10-20-23-49-28-1024x609.png?v=1792512039" alt="" class="wp-image-8816" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/10/chrome_2026-10-20-23-49-28-1024x609.png?v=1792512039 1024w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/10/chrome_2026-10-20-23-49-28-600x357.png?v=1792512039 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/10/chrome_2026-10-20-23-49-28-767x456.png?v=1792512039 767w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/10/chrome_2026-10-20-23-49-28.png?v=1792512039 1059w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">AI 生成的盲點：為什麼 Flexbox 在這裡會翻車？</h2>



<p class="wp-block-paragraph">如果讓 AI 直接用 <code>display: flex</code> 來處理這種左側是標籤、右側是標題加內文的卡片，通常會遇到以下幾個痛點：</p>



<ol start="1" class="wp-block-list">
<li>高度與垂直對齊難以控制：當右側的文字因為換行變成兩行或三行時，左側的標籤或圖示往往會跟著亂跑，無法與右側內容保持一致的垂直置中或頂端對齊。</li>



<li>巢狀結構過於肥胖：為了模擬左右兩欄，AI 往往會生出好幾層 <code>div</code> 來互相巢狀包裹，導致 HTML 結構變得很冗長。</li>



<li>欄位寬度不穩定：如果左側的標籤文字長度不一致，會直接導致右側的文字區域跟著被擠壓變形。</li>
</ol>



<h2 class="wp-block-heading">核心原理：為什麼改用 CSS Grid？</h2>



<p class="wp-block-paragraph">為了達到類似傳統表格（ tr 搭配兩個 td ）的嚴謹對齊效果，最佳解法其實是 <strong>CSS Grid</strong>。</p>



<p class="wp-block-paragraph">我們只需要將卡片本身設為 <code>display: grid</code>，並透過 <code>grid-template-columns: 200px 1fr</code>：</p>



<ul class="wp-block-list">
<li>第一欄（左側）固定寬度或給予適當的空間放標籤與圖示。</li>



<li>第二欄（右側）設定為 <code>1fr</code>，自動佔滿剩餘的所有寬度。</li>
</ul>



<p class="wp-block-paragraph">這樣一來，不管右側的文字換幾行、內容有多長，左右兩欄的對齊關係依然穩固如山，完全不需要擔心版面變形。</p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">這是一篇針對此次 CSS 版面調整所撰寫的技術部落格文章，內容包含原理簡介、AI 生成常見陷阱、實際遇到的問題以及解法，並已將程式碼對照調整為清楚的 Before 與 After 區塊。</p>



<h2 class="wp-block-heading">從 AI 生成的 Flex 陷阱談起：如何用 CSS Grid 打造完美的左右雙欄卡片</h2>



<p class="wp-block-paragraph">在網頁前端開發中，我們經常需要將區塊拆分成左右兩欄，例如左邊放標籤或圖示、右邊放標題與內文。當我們把任務交給 AI 生成時，最常見的反應就是直接使用 Flexbox 排版。</p>



<p class="wp-block-paragraph">雖然 Flexbox 非常好用，但在處理多行、不規則高度或是希望呈現傳統表格對齊（例如類似 HTML 表格中的 tr 包含兩個 td ）的結構時，使用 Flexbox 往往會衍生出許多意想不到的排版災難。</p>



<h2 class="wp-block-heading">AI 生成的盲點：為什麼 Flexbox 在這裡會翻車？</h2>



<p class="wp-block-paragraph">如果讓 AI 直接用 <code>display: flex</code> 來處理這種左側是標籤、右側是標題加內文的卡片，通常會遇到以下幾個痛點：</p>



<ol start="1" class="wp-block-list">
<li>高度與垂直對齊難以控制：當右側的文字因為換行變成兩行或三行時，左側的標籤或圖示往往會跟著亂跑，無法與右側內容保持一致的垂直置中或頂端對齊。</li>



<li>巢狀結構過於肥胖：為了模擬左右兩欄，AI 往往會生出好幾層 <code>div</code> 來互相巢狀包裹，導致 HTML 結構變得很冗長。</li>



<li>欄位寬度不穩定：如果左側的標籤文字長度不一致，會直接導致右側的文字區域跟著被擠壓變形。</li>
</ol>



<h2 class="wp-block-heading">核心原理：為什麼改用 CSS Grid？</h2>



<p class="wp-block-paragraph">為了達到類似傳統表格（ tr 搭配兩個 td ）的嚴謹對齊效果，最佳解法其實是 <strong>CSS Grid</strong>。</p>



<p class="wp-block-paragraph">我們只需要將卡片本身設為 <code>display: grid</code>，並透過 <code>grid-template-columns: 200px 1fr</code>：</p>



<ul class="wp-block-list">
<li>第一欄（左側）固定寬度或給予適當的空間放標籤與圖示。</li>



<li>第二欄（右側）設定為 <code>1fr</code>，自動佔滿剩餘的所有寬度。</li>
</ul>



<p class="wp-block-paragraph">這樣一來，不管右側的文字換幾行、內容有多長，左右兩欄的對齊關係依然穩固如山，完全不需要擔心版面變形。</p>



<h2 class="wp-block-heading">實戰修改前後對照</h2>



<h3 class="wp-block-heading">CSS 修改前後對照</h3>



<p class="wp-block-paragraph">Before（修改前）：</p>



<p class="wp-block-paragraph">CSS</p>



<pre class="wp-block-code"><code>/* Right: 3 Alignment Pillars */
.alignment-pillars {
  position: absolute;
  top: 170px;
  left: 510px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.align-card {
  padding: 18px 26px;
  opacity: 0;
}
</code></pre>



<p class="wp-block-paragraph">After（修改後）：</p>



<p class="wp-block-paragraph">CSS</p>



<pre class="wp-block-code"><code>/* Right: 3 Alignment Pillars */
.alignment-pillars {
  position: absolute;
  top: 170px;
  left: 510px;
  display: flex;
  flex-direction: column;
  gap: 18px;
  width: 600px;
}

.align-card {
  padding: 18px 26px;
  opacity: 0;
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 20px;
  align-items: center;
}

.align-card-left {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
}

.align-card-right {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
</code></pre>



<h3 class="wp-block-heading">HTML 修改前後對照</h3>



<p class="wp-block-paragraph">Before（修改前）：</p>



<p class="wp-block-paragraph">HTML</p>



<pre class="wp-block-code"><code><code>&lt;!-- Pillar 1 -->
  &lt;div class="align-card align-1 card-base">
    &lt;div class="pillar-tag p1">心法 1：釐清真正的需求&lt;/div>
    &lt;div class="pillar-title">拿到任務先別急著打開檔案或叫 AI 產出&lt;/div>
    &lt;div class="pillar-desc">多問幾個為什麼，找出背後真正要解決的核心問題。先問清定價需求，一頁表格就能直擊核心。&lt;/div>
  &lt;/div>
</code></code></pre>



<p class="wp-block-paragraph">After（修改後）：</p>



<p class="wp-block-paragraph">HTML</p>



<pre class="wp-block-code"><code><code>&lt;!-- Pillar 1 -->
  &lt;div class="align-card align-1 card-base">
    &lt;div class="align-card-left">
      &lt;div class="pillar-tag p1">心法 1：釐清真正的需求&lt;/div>
    &lt;/div>
    &lt;div class="align-card-right">
      &lt;div class="pillar-title">拿到任務先別急著打開檔案或叫 AI 產出&lt;/div>
      &lt;div class="pillar-desc">多問幾個為什麼，找出背後真正要解決的核心問題。先問清定價需求，一頁表格就能直擊核心。&lt;/div>
    &lt;/div>
  &lt;/div>
</code></code></pre>



<h2 class="wp-block-heading">總結</h2>



<p class="wp-block-paragraph">下次當你需要處理類似表格列、左右對齊的區塊時，如果 AI 自動幫你寫了滿滿的 Flexbox 巢狀結構，不妨主動要求它改用 <strong>CSS Grid</strong>。只要定義好欄位寬度比例，就能用最乾淨的程式碼，換取最穩定、最不容易跑版的畫面表現。</p>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/10/css-from-flex-to-grid/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>如何為 WordPress 主題無痛加入深色模式？Git Patch 與高效率 Prompt 實戰</title>
		<link>https://stackoverflow.max-everyday.com/2026/10/wordpress-dark-mode-git-patch-prompt/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/10/wordpress-dark-mode-git-patch-prompt/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Thu, 15 Oct 2026 16:19:35 +0000</pubDate>
				<category><![CDATA[WordPress筆記]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=8796</guid>

					<description><![CDATA[在現代網頁設計中，深色模式（Dark Mode ...]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="572" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/10/watermarked_img_4204396195813658961_clean-1024x572.jpg?v=1792081142" alt="" class="wp-image-8798" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/10/watermarked_img_4204396195813658961_clean-1024x572.jpg?v=1792081142 1024w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/10/watermarked_img_4204396195813658961_clean-767x428.jpg?v=1792081142 767w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/10/watermarked_img_4204396195813658961_clean-600x335.jpg?v=1792081142 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/10/watermarked_img_4204396195813658961_clean.jpg?v=1792081142 1376w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">在現代網頁設計中，深色模式（Dark Mode / Dark Theme）已經是用戶體驗（UX）的基本標配。除了降低在暗處閱讀時的眼部疲勞，也能延長 OLED 螢幕的電池續航力。</p>



<p class="wp-block-paragraph">本篇技術筆記以開源主題 <strong>Guntenbee</strong> 為例，完整記錄如何架構一個具備「<strong>系統主題偏好自動偵測</strong> + <strong>Cookie 記憶</strong> + <strong>切換按鈕</strong> + <strong>防閃爍 (Anti-flicker)</strong>」的深色模式方案。同時針對日後「<strong>原作者主題升級</strong>」時如何以零成本（Git Patch / Child Theme）或極低 Token 的 AI 提示詞無痛重新套用進行深度解析。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">一、核心需求與架構設計</h2>



<p class="wp-block-paragraph">一個健全的深色模式切換機制需要具備以下要點：</p>



<ol class="wp-block-list">
<li><strong>使用者優先權階層</strong>：
<ul class="wp-block-list">
<li>若使用者曾在站上點擊切換過，以 <strong>Cookie 儲存的偏好</strong> 為最優先。</li>



<li>若為首次造訪或未設定 Cookie，自動偵測使用者的<strong>系統外觀模式</strong>（<code>prefers-color-scheme: dark</code>）。</li>
</ul>
</li>



<li><strong>避免白光閃爍（Anti-flicker / FOUC）</strong>：
<ul class="wp-block-list">
<li>瀏覽器解析 HTML 時，如果等到完整腳本下載並在 DOMContentLoaded 才執行加 class，畫面上會出現短暫的白光閃爍。因此需在 <code>&lt;head></code> 注入極輕量的行內（Inline）腳本提早設定 class。</li>
</ul>
</li>



<li><strong>直覺易用的開關位置</strong>：
<ul class="wp-block-list">
<li>將切換開關置入 Header 頂部導覽列（<code>&lt;div class="head-mast-inner"></code>），確保各裝置與版型都能一致顯示。</li>
</ul>
</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">二、功能實作步驟</h2>



<h3 class="wp-block-heading">1. 樣式實作：獨立樣式表 (<code>css/dark-theme.css</code>)</h3>



<p class="wp-block-paragraph">將所有深色模式樣式統一抽離至獨立檔案，避免直接污染原作者的 <code>style.css</code>，大幅降低後續維護與合併時的衝突風險。</p>



<pre class="wp-block-code"><code>/* ==========================================================================
   Dark Theme Styles
   ========================================================================== */

/* 全域背景與文字 */
body.theme-dark {
  background-color: #121417;
  color: #c9d1d9;
}

body.theme-dark h1,
body.theme-dark h2,
body.theme-dark h3,
body.theme-dark h4,
body.theme-dark h5,
body.theme-dark h6 {
  color: #f0f6fc;
}

/* 頂部導覽、底欄與行動端選單 */
body.theme-dark .head-mast,
body.theme-dark .head-outro,
body.theme-dark .navigation-mobile-wrap {
  background-color: #181b20;
  color: #c9d1d9;
}

/* 下拉選單 */
body.theme-dark .navigation-main ul {
  background-color: #1a1e24;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.45);
  border: 1px solid #2b3036;
}

/* 輸入框與表單元件 */
body.theme-dark input&#91;type="text"],
body.theme-dark input&#91;type="search"],
body.theme-dark select,
body.theme-dark textarea {
  background-color: #1a1e24;
  color: #e6edf3;
  border-color: #343a42;
}

/* 主題切換按鈕與 SVG 圖示切換 */
.theme-switch-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: transparent;
  border: 0;
  cursor: pointer;
  color: inherit;
  transition: color 0.18s ease, background-color 0.18s ease;
}

.theme-switch-icon svg {
  width: 18px;
  height: 18px;
  fill: currentColor;
}

/* 淺色模式顯示月亮，深色模式顯示太陽 */
.theme-switch-icon .icon-sun { display: none; }
.theme-switch-icon .icon-moon { display: inline-block; }
body.theme-dark .theme-switch-icon .icon-sun { display: inline-block; }
body.theme-dark .theme-switch-icon .icon-moon { display: none; }</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">2. 行為邏輯：偵測與持久化 (<code>js/theme-switch.js</code>)</h3>



<p class="wp-block-paragraph">透過原生 JavaScript 實現無相依性（Vanilla JS）的偵測與 Cookie 儲存：</p>



<pre class="wp-block-code"><code>(function () {
  'use strict';

  var COOKIE_NAME = 'guntenbee_theme';
  var COOKIE_DAYS = 365;

  function getCookie(name) {
    var match = document.cookie.match(new RegExp('(^|;\\s*)' + name + '=(&#91;^;]+)'));
    return match ? decodeURIComponent(match&#91;2]) : null;
  }

  function setCookie(name, value, days) {
    var expires = '';
    if (days) {
      var date = new Date();
      date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
      expires = '; expires=' + date.toUTCString();
    }
    document.cookie = name + '=' + encodeURIComponent(value) + expires + '; path=/; SameSite=Lax';
  }

  function getSystemTheme() {
    return (window.matchMedia &amp;&amp; window.matchMedia('(prefers-color-scheme: dark)').matches)
      ? 'dark'
      : 'light';
  }

  function getPreferredTheme() {
    var savedTheme = getCookie(COOKIE_NAME);
    return (savedTheme === 'dark' || savedTheme === 'light') ? savedTheme : getSystemTheme();
  }

  function applyTheme(theme) {
    var isDark = (theme === 'dark');
    document.body.classList.toggle('theme-dark', isDark);
    document.body.classList.toggle('theme-light', !isDark);
    document.documentElement.classList.toggle('theme-dark', isDark);
    document.documentElement.classList.toggle('theme-light', !isDark);

    var toggles = document.querySelectorAll('.theme-switch-toggle');
    toggles.forEach(function (btn) {
      btn.setAttribute('aria-pressed', isDark ? 'true' : 'false');
      btn.setAttribute('title', isDark ? '切換至淺色模式' : '切換至深色模式');
    });
  }

  function init() {
    applyTheme(getPreferredTheme());

    document.addEventListener('click', function (e) {
      var toggle = e.target.closest('.theme-switch-toggle');
      if (toggle) {
        e.preventDefault();
        var currentTheme = document.body.classList.contains('theme-dark') ? 'dark' : 'light';
        var nextTheme = (currentTheme === 'dark') ? 'light' : 'dark';
        setCookie(COOKIE_NAME, nextTheme, COOKIE_DAYS);
        applyTheme(nextTheme);
      }
    });

    // 監聽作業系統外觀模式動態變化
    if (window.matchMedia) {
      window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function () {
        if (!getCookie(COOKIE_NAME)) {
          applyTheme(getSystemTheme());
        }
      });
    }
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', init);
  } else {
    init();
  }
})();</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">3. WordPress 資源載入與防閃爍 (<code>inc/scripts-styles.php</code>)</h3>



<p class="wp-block-paragraph">在 <code>wp_enqueue_scripts</code> 鉤子中註冊資源，並加入極速 Inline 腳本：</p>



<pre class="wp-block-code"><code>// Enqueue 樣式與腳本
wp_register_style( 'gutenbee-dark-theme', get_theme_file_uri( '/css/dark-theme.css' ), array( 'gutenbee-style' ), gutenbee_asset_version() );
wp_enqueue_style( 'gutenbee-dark-theme' );

// 防閃爍腳本：在頁面剛開始解析 DOM 時搶先將 theme-dark 注入 &lt;html&gt;
$anti_flicker_js = "(function(){try{var m=document.cookie.match(/(^|;\\s*)guntenbee_theme=(&#91;^;]+)/);var t=m?decodeURIComponent(m&#91;2]):null;var d=(window.matchMedia&amp;&amp;window.matchMedia('(prefers-color-scheme: dark)').matches)?'dark':'light';if((t||d)==='dark'){document.documentElement.classList.add('theme-dark');}}catch(e){}})();";
wp_add_inline_script( 'gutenbee-dependencies', $anti_flicker_js, 'before' );

wp_register_script( 'gutenbee-theme-switch', get_theme_file_uri( '/js/theme-switch.js' ), array(), gutenbee_asset_version(), true );
wp_enqueue_script( 'gutenbee-theme-switch' );</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">4. 範本標籤與按鈕輸出 (<code>inc/template-tags.php</code> &amp; Header Templates)</h3>



<ol class="wp-block-list">
<li>定義輔助函數：<code>function gutenbee_the_theme_switch_button() { ?> &lt;button type="button" class="theme-switch-toggle" aria-label="切換深淺模式"> &lt;span class="theme-switch-icon" aria-hidden="true"> &lt;svg class="icon-moon" viewBox="0 0 24 24">&lt;path d="M12.3 2a10 10 0 0 0-.19 14 10 10 0 0 0 11.63 4A10 10 0 1 1 12.3 2z"/>&lt;/svg> &lt;svg class="icon-sun" viewBox="0 0 24 24">&lt;circle cx="12" cy="12" r="5"/>&lt;line x1="12" y1="1" x2="12" y2="3" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>&lt;line x1="12" y1="21" x2="12" y2="23" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>&lt;line x1="4.22" y1="4.22" x2="5.64" y2="5.64" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>&lt;line x1="18.36" y1="18.36" x2="19.78" y2="19.78" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>&lt;line x1="1" y1="12" x2="3" y2="12" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>&lt;line x1="21" y1="12" x2="23" y2="12" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>&lt;line x1="4.22" y1="19.78" x2="5.64" y2="18.36" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>&lt;line x1="18.36" y1="5.64" x2="19.78" y2="4.22" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>&lt;/svg> &lt;/span> &lt;/button> &lt;?php }</code></li>



<li>在 <code>template-parts/header/header-full.php</code>、<code>header-split.php</code>、<code>header-navbar.php</code> 的 <code>&lt;div class="head-mast-inner"></code> 內部直接呼叫 <code>gutenbee_the_theme_switch_button()</code> 即可完美呈現。</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">三、未來原作者升級主題時的處理策略</h2>



<p class="wp-block-paragraph">當原主題作者發布新版本更新時，若直接覆蓋整個主題資料夾，客製化代碼將會遺失。以下提供三種不同維護情境的應對方式：</p>



<h3 class="wp-block-heading">策略 A：建立子主題（Child Theme）—— 永遠不被覆蓋（推薦最佳實踐）</h3>



<p class="wp-block-paragraph">WordPress 的標準升級防禦機制是子主題。只需將新寫好的 <code>dark-theme.css</code>、<code>theme-switch.js</code> 及對應 template parts 放進子主題資料夾，日後父主題無論升級幾次，客製化邏輯都不會被覆蓋。</p>



<h3 class="wp-block-heading">策略 B：利用 Git Patch 自動打補丁（零 Token 快速升級）</h3>



<p class="wp-block-paragraph">若習慣直接於主題目錄工作，建議在功能完成時立即產生 patch 檔案備份：</p>



<pre class="wp-block-code"><code># 產出補丁檔
git diff &gt; dark-theme.patch</code></pre>



<p class="wp-block-paragraph">當日後原作者有新版發布時：</p>



<pre class="wp-block-code"><code># 下載並解壓縮覆蓋原主題後，執行一鍵套用
git apply --reject --whitespace=fix dark-theme.patch</code></pre>



<p class="wp-block-paragraph"><code>git apply</code> 具備自動比對行號上下文與建立新檔案的能力，速度快且完全不花費任何 AI token。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">策略 C：低 Token 的精準 AI 提示詞（AI Prompt Template）</h3>



<p class="wp-block-paragraph">若在遠端或未配備 Git 的環境，需請 AI 助理重新在原作者新版主題植入 Dark Theme 功能時，<strong>千萬不要使用模糊指令</strong>（例如「<em>幫我在這個主題加深色模式</em>」，這會讓 AI 花費數萬 Token 去探索全文結構與測試選擇器）。</p>



<p class="wp-block-paragraph">直接複製使用以下經結構化優化的 <strong>精準 Prompt</strong>：</p>



<pre class="wp-block-code"><code>請為 @guntenbee 主題實作 Dark Theme 功能。請直接依照以下規格建立檔案與注入代碼，不需漫遊搜尋其他檔案：

1. 新增樣式與腳本：
   - 建立 `css/dark-theme.css`：定義 `body.theme-dark` 樣式（深色底色 #121417、文字 #c9d1d9、容器/選單 #181b20）與 `.theme-switch-toggle` 按鈕 SVG 切換動態。
   - 建立 `js/theme-switch.js`：讀取/寫入 Cookie `guntenbee_theme`（效期 365 天）；若無 Cookie 則以 `prefers-color-scheme: dark` 為準，並監聽 OS 主題變化與按鈕點擊事件。

2. 註冊與防閃爍（修改 `inc/scripts-styles.php`）：
   - 在 `gutenbee_enqueue_scripts` 中以 `wp_enqueue_style` 載入 `dark-theme.css`。
   - 注入 Inline Script 到 `&lt;head&gt;`：若 Cookie 或系統偏好為 dark，即時加上 `document.documentElement.classList.add('theme-dark')` 以防止白光閃爍。
   - 以 `wp_enqueue_script` 載入 `theme-switch.js`。

3. 按鈕與鉤子整合：
   - 在 `inc/template-tags.php` 新增 `gutenbee_the_theme_switch_button()` 輸出太陽/月亮按鈕 HTML。
   - 在 `template-parts/header/header-*.php` 各樣板的 `&lt;div class="head-mast-inner"&gt;` 的 `head-content-slot` 中呼叫該按鈕函式。
   - 在 `inc/default-hooks.php` 的 `gutenbee_body_class` 過濾器中檢查 `$_COOKIE&#91;'guntenbee_theme']`，有 dark 值即附加 `theme-dark` class。</code></pre>



<h4 class="wp-block-heading">為什麼這個 Prompt 具備高性價比（Low Token Usage）？</h4>



<ol class="wp-block-list">
<li><strong>消除探勘步驟</strong>：精確指出檔案名稱（如 <code>inc/scripts-styles.php</code>、<code>template-parts/header/header-*.php</code>），AI 不需調用目錄搜尋工具消耗大量 Context Window。</li>



<li><strong>精準函式命名</strong>：直接給予目標鉤子（<code>gutenbee_body_class</code>、<code>gutenbee_enqueue_scripts</code>），AI 思考路徑縮短，輸出 token 減少 70% 以上。</li>



<li><strong>成果可預測且易於維護</strong>：模組化規範使每一次生成的樣式結構一致，日後維護與問題排查極為單純。</li>
</ol>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/10/wordpress-dark-mode-git-patch-prompt/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>CSP (Content Security Policy) 的網站要如何安全的使用 Inline script</title>
		<link>https://stackoverflow.max-everyday.com/2026/06/csp-content-security-policy-%e7%9a%84%e7%b6%b2%e7%ab%99%e8%a6%81%e5%a6%82%e4%bd%95%e5%ae%89%e5%85%a8%e7%9a%84%e4%bd%bf%e7%94%a8-inline-script/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/06/csp-content-security-policy-%e7%9a%84%e7%b6%b2%e7%ab%99%e8%a6%81%e5%a6%82%e4%bd%95%e5%ae%89%e5%85%a8%e7%9a%84%e4%bd%bf%e7%94%a8-inline-script/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Thu, 18 Jun 2026 09:01:22 +0000</pubDate>
				<category><![CDATA[css筆記]]></category>
		<category><![CDATA[css]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=8583</guid>

					<description><![CDATA[當你在幫網站做健康檢查，看到弱掃報告（ 像是 Z...]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">當你在幫網站做健康檢查，看到弱掃報告（ 像是 ZAP ）跳出一個橘黃色的 Medium 警告，寫著 <code>style-src 'unsafe-inline'</code> 或是發現 <code>script-src</code> 滿是漏洞時，心裡是不是頓時涼了一半？</p>



<p class="wp-block-paragraph">簡單來說，如果你的 CSP （ 網頁安全政策 ）開了 <code>unsafe-inline</code> ，就等於是在大門裝了密碼鎖，卻把密碼用便利貼貼在門口一樣。駭客只要找到機會塞一段惡意腳本（ XSS 攻擊 ），你的網站就直接變成他的遊樂場。</p>



<p class="wp-block-paragraph">但是偏偏像是 Google Tag Manager （ GTM ）這種必裝的分析工具，官方給的程式碼裡面就是有一大段 Inline Script ：</p>



<p class="wp-block-paragraph">HTML</p>



<pre class="wp-block-code"><code>&lt;script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"&gt;&lt;/script&gt;
&lt;script&gt;
  window.dataLayer = window.dataLayer || &#91;];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'G-XXXXXXXXXX');
&lt;/script&gt;
</code></pre>



<p class="wp-block-paragraph">既想要防禦 XSS 攻擊，又不能把 GTM <sup></sup>拔掉，這時候你有兩條路可以走，讓我們來看看這兩個相愛相殺的解決方案。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">方案一：使用 Nonce （ 一次性密碼鎖 ）</h3>



<p class="wp-block-paragraph">這個方法就像是去看演唱會，每次進場工作人員都會在你的手上蓋一個當天限定、過期失效的印章。</p>



<p class="wp-block-paragraph">在 CSP 標頭（ Header ）裡，你可以這樣設定：</p>



<p class="wp-block-paragraph">HTTP</p>



<pre class="wp-block-code"><code>Content-Security-Policy: script-src 'nonce-每天換的神秘亂數密碼'; img-src www.googletagmanager.com
</code></pre>



<p class="wp-block-paragraph">然後在你的網頁程式碼中，那段 GTM 的標籤也必須帶上相同的密碼：</p>



<p class="wp-block-paragraph">HTML</p>



<pre class="wp-block-code"><code>&lt;script nonce='每天換的神秘亂數密碼'&gt;
  // GTM 的扣（Code）放這裡
&lt;/script&gt;
</code></pre>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 工程師真心話</h4>



<ul class="wp-block-list">
<li><strong>優點</strong>：超級安全。因為駭客根本猜不到你下一個 Request 的亂數密碼是什麼，就算他成功塞了惡意指令，也會因為沒有通關密碼而被瀏覽器直接擋在門外。</li>



<li><strong>缺點（ 也就是坑 ）</strong>：這非常考驗後端的大腦。你的伺服器必須在「 每次 」收到請求時，都用高強度的加密演算法生出一組全新的隨機字串。最慘的是，你的網頁從此跟「 回應快取 」（ Response Cache ）說再見，因為一旦網頁被快取，密碼就不會變了，那這個鎖就形同虛設。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">方案二：使用 Hash （ 驗收指紋認證 ）</h3>



<p class="wp-block-paragraph">如果你的網站是 SPA （ 單頁應用程式 ），或是部署在 GitHub Pages 這種根本沒有後端可以幫忙生密碼的靜態伺服器，那 Hash 就是你的救星。</p>



<p class="wp-block-paragraph">這個概念是，瀏覽器會直接去核對這段程式碼的「 指紋 」。</p>



<p class="wp-block-paragraph">步驟非常簡單，把 <code>&lt;script&gt;</code> 到 <code>&lt;/script&gt;</code> 之間的程式碼內容，丟到 <a target="_blank" rel="noreferrer noopener" href="https://stackoverflow.max-everyday.com/wp-admin/post.php?post=8583&amp;action=edit">SHA256 線上計算工具</a> 裡面去跑一下，會得到一串像是 <code>0bbd063b7...</code> 的雜湊值（ Hash ）。</p>



<p class="wp-block-paragraph">接著把這串指紋放進你的 CSP 設定裡：</p>



<p class="wp-block-paragraph">HTTP</p>



<pre class="wp-block-code"><code>Content-Security-Policy: script-src 'sha256-計算出來的那串指紋'; img-src www.googletagmanager.com
</code></pre>



<h4 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> 工程師真心話</h4>



<ul class="wp-block-list">
<li><strong>優點</strong>：前端自己就能搞定，不需要後端伺服器配合，而且網頁依然可以開開心心地做快取，提升載入速度。</li>



<li><strong>缺點（ 最雷的地方 ）</strong>：
<ol start="1" class="wp-block-list">
<li><strong>字元敏感度破表</strong>：SHA256 是一個極度龜毛的演算法。只要你的程式碼裡面多了一個空格、少了一個換行，甚至不同工程師的電腦存檔時，斷行符號一個是 LF （ <code>\n</code> ）一個是 CRLF （ <code>\r\n</code> ），算出來的指紋就完全不一樣。指紋一對不上，你的 GTM 就會直接被 CSP 射下來。</li>



<li><strong>維護地獄</strong>：哪天行銷團隊突然要求修改 GTM 裡面的參數，只要動到一個字，你就必須重新計算一次 Hash 值、重新更新 CSP 標頭。如果交接沒做好，後續接手的工程師改了程式碼發現網站功能壞掉，可能要在電腦前哭著找兇手找很久。</li>
</ol>
</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">總結防禦指南</h3>



<p class="wp-block-paragraph">想要高枕無憂、後端架構也撐得住，請選 <strong>Nonce</strong> 。</p>



<p class="wp-block-paragraph">如果是靜態網站、追求速度與快取，請選 <strong>Hash</strong> ，但每次改動程式碼時，請記得去燒香拜拜順便更新指紋。</p>



<p class="wp-block-paragraph">總之，快把 <code>unsafe-inline</code> 從你的 CSP 裡面拿掉，別再讓你的網站裸奔了。</p>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/06/csp-content-security-policy-%e7%9a%84%e7%b6%b2%e7%ab%99%e8%a6%81%e5%a6%82%e4%bd%95%e5%ae%89%e5%85%a8%e7%9a%84%e4%bd%bf%e7%94%a8-inline-script/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>網頁開發者必看！用白話秒懂 CSS Injection 與 CSP 防禦</title>
		<link>https://stackoverflow.max-everyday.com/2026/06/css-injection-csp-url/</link>
					<comments>https://stackoverflow.max-everyday.com/2026/06/css-injection-csp-url/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Thu, 18 Jun 2026 06:39:22 +0000</pubDate>
				<category><![CDATA[css筆記]]></category>
		<category><![CDATA[React 筆記]]></category>
		<category><![CDATA[css]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=8572</guid>

					<description><![CDATA[為什麼連寫個看起來無害的 CSS 都會被瀏覽器當...]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="572" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/06/css-injection-csp-url__clean-1024x572.jpg?v=1781764740" alt="" class="wp-image-8579" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2026/06/css-injection-csp-url__clean-1024x572.jpg?v=1781764740 1024w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/06/css-injection-csp-url__clean-600x335.jpg?v=1781764740 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/06/css-injection-csp-url__clean-768x429.jpg?v=1781764740 768w, https://stackoverflow.max-everyday.com/wp-content/uploads/2026/06/css-injection-csp-url__clean.jpg?v=1781764740 1376w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">為什麼連寫個看起來無害的 CSS 都會被瀏覽器當成恐怖份子。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">瀏覽器的大內總管：CSP 到底在嚴格什麼？</h2>



<p class="wp-block-paragraph">各位前端與後端苦力們，有沒有遇過這種慘劇？</p>



<p class="wp-block-paragraph">當你興高采烈地在網站加上這行內容安全政策（CSP）：</p>



<pre class="wp-block-code"><code><code>Content-Security-Policy: default-src 'self';</code></code></pre>



<p class="wp-block-paragraph">本以為從此高枕無憂，結果下一秒打開網頁，發現自己寫的行內腳本（inline-script）全部陣亡：</p>



<pre class="wp-block-code"><code><code>&lt;script&gt;console.log('連我都不能跑是怎樣');&lt;/script&gt;</code></code></pre>



<p class="wp-block-paragraph">好啦，大家都知道 JavaScript 權限大、壞人最愛用，所以瀏覽器預設不讓它亂跑很合理。為了安撫大內總管，我們還得乖乖去算雜湊值（Hash）或是塞個 nonce 安全憑證，像是這樣：</p>



<pre class="wp-block-code"><code><code>Content-Security-Policy: default-src 'self'; script-src 'sha256-xxx...';</code></code></pre>



<p class="wp-block-paragraph">但是，最讓人傻眼的是，連單純想幫網頁化妝的行內樣式（inline-style）也被一起關進大牢了：</p>



<pre class="wp-block-code"><code><code>&lt;style&gt;h1 { color: yellow; }&lt;/style&gt;</code></code></pre>



<p class="wp-block-paragraph">CSS 到底做錯了什麼？它只是個孩子啊！</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">警匪片現場：當 CSS 變成滲透工具</h2>



<p class="wp-block-paragraph">資安世界有三大神聖支柱：機密性、完整性、可用性。而隨便亂加的 CSS，其實正在默默破壞這一切。</p>



<h3 class="wp-block-heading">疑犯一號：DOM 元素私生子（破壞完整性）</h3>



<p class="wp-block-paragraph">你可能會想：「這網頁是我寫的，裡面的 CSS 當然也是我寫的啊！」</p>



<p class="wp-block-paragraph">事情可沒那麼簡單。在 JavaScript 的世界裡，壞人可以用各種神奇手法動態產生元素：</p>



<p class="wp-block-paragraph">JavaScript</p>



<pre class="wp-block-code"><code>let style = document.createElement('style');
style.innerText = 'h1 { color: blue; }';
document.body.appendChild(style);
</code></pre>



<p class="wp-block-paragraph">這段程式碼一旦被惡意注入，它就能神不知鬼不覺地改掉你的網頁外觀。這就是為什麼瀏覽器乾脆一不做二不休，預設把所有沒登記過的行內樣式全部封鎖。</p>



<h3 class="wp-block-heading">疑犯二號：假藉美化名義的間諜（破壞機密性）</h3>



<p class="wp-block-paragraph">CSS 裡面有兩個看起來很無辜、但實際上超常被當作間諜的語法： <code>@import</code> 和 <code>url()</code> 。</p>



<p class="wp-block-paragraph">當你用了背景圖片：</p>



<pre class="wp-block-code"><code><code>background-image: url(https://example.com/spy.jpg);</code></code></pre>



<p class="wp-block-paragraph">瀏覽器看到這行，就會自動發出一個請求去下載圖片。這時候，壞人就可以利用這個機制搞鬼：</p>



<ul class="wp-block-list">
<li><strong>偷看你的行蹤（Beacon 技術）：</strong> 只要把圖片網址加上個人專屬的編碼，當你一打開網頁，壞人的伺服器收到圖片請求，就知道「喔！某某某在幾點幾分看了這個頁面！」</li>



<li><strong>Cookie 順風車：</strong> 如果網站沒設定好，這個請求甚至會順便把你的 Cookie 跨站送出去，直接把你的登入狀態雙手奉上。</li>
</ul>



<p class="wp-block-paragraph">所以，想要在有 CSP 的防護下安全地秀出圖片，你還必須跟總管報備圖片的白色名單：</p>



<pre class="wp-block-code"><code><code>Content-Security-Policy: default-src 'self'; style-src 'sha256-...'; img-src http://信任的圖片來源;</code></code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">結論</h2>



<p class="wp-block-paragraph">在這個壞人招數層出不窮的時代，網頁開發者真的不能只活在「CSS 只是用來排版」的粉紅泡泡裡。多了解一點 CSP 的龜毛規則，雖然設定時會寫到抓狂，但至少能保住大家的飯碗，不讓網站變成駭客的免費遊樂園！</p>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2026/06/css-injection-csp-url/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Use the :has() Selector in CSS</title>
		<link>https://stackoverflow.max-everyday.com/2024/12/how-to-use-the-has-selector-in-css/</link>
					<comments>https://stackoverflow.max-everyday.com/2024/12/how-to-use-the-has-selector-in-css/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Thu, 05 Dec 2024 01:41:05 +0000</pubDate>
				<category><![CDATA[css筆記]]></category>
		<category><![CDATA[css]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=6035</guid>

					<description><![CDATA[之前使用過 :not() 覺得超級的實用，例如：...]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1024" height="1024" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2024/12/89ac7fc5-1ae6-4a94-b35c-144dd7704fdb.jpeg" alt="" class="wp-image-6037" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2024/12/89ac7fc5-1ae6-4a94-b35c-144dd7704fdb.jpeg?v=1733363050 1024w, https://stackoverflow.max-everyday.com/wp-content/uploads/2024/12/89ac7fc5-1ae6-4a94-b35c-144dd7704fdb-600x600.jpeg?v=1733363050 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2024/12/89ac7fc5-1ae6-4a94-b35c-144dd7704fdb-300x300.jpeg?v=1733363050 300w, https://stackoverflow.max-everyday.com/wp-content/uploads/2024/12/89ac7fc5-1ae6-4a94-b35c-144dd7704fdb-768x768.jpeg?v=1733363050 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">之前使用過 :not() 覺得超級的實用，例如：選取所有checkbox 狀態是沒被打勾的。今天要來學習使用 :has().</p>



<h2 class="wp-block-heading">相關文章</h2>



<ul class="wp-block-list">
<li>:has()<br><a href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/:has">https://developer.mozilla.org/zh-CN/docs/Web/CSS/:has</a></li>



<li>CSS :has() Pseudo-class<br><a href="https://www.w3schools.com/cssref/sel_has.php">https://www.w3schools.com/cssref/sel_has.php</a></li>



<li>:has() 個案研究<br><a href="https://developer.chrome.com/blog/css-ui-ecommerce-has?hl=zh-tw">https://developer.chrome.com/blog/css-ui-ecommerce-has?hl=zh-tw</a></li>



<li>How to Use the :has() Selector in CSS<br><a href="https://www.freecodecamp.org/news/how-to-use-the-has-selector-in-css/">https://www.freecodecamp.org/news/how-to-use-the-has-selector-in-css/</a></li>
</ul>



<p class="wp-block-paragraph">影片：Learn CSS :not() and :has() selector in 6 Minutes<br><a href="https://www.youtube.com/watch?v=-pQZLQakz-c">https://www.youtube.com/watch?v=-pQZLQakz-c</a></p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Learn CSS :not() and :has() selector in 6 Minutes" width="640" height="360" src="https://www.youtube.com/embed/-pQZLQakz-c?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p class="wp-block-paragraph">滿神奇的，居然完全沒使用 javascript 就到過 filter 功能。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2024/12/how-to-use-the-has-selector-in-css/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>tabulator 的寬度無法overflow:hidden</title>
		<link>https://stackoverflow.max-everyday.com/2023/08/tabulator-width-overflow-hidden/</link>
					<comments>https://stackoverflow.max-everyday.com/2023/08/tabulator-width-overflow-hidden/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Fri, 04 Aug 2023 10:33:26 +0000</pubDate>
				<category><![CDATA[css筆記]]></category>
		<category><![CDATA[css]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=4968</guid>

					<description><![CDATA[正常情況下, overflow 的部分被隱藏, ...]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">正常情況下, overflow 的部分被隱藏, 並在內部元件產生橫向的scroll bar.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="535" height="578" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2023/08/2023-08-04-18_24_54-Window.jpg" alt="" class="wp-image-4970"/></figure>



<p class="wp-block-paragraph">異常情況, 是無法產生 scrollbar, 畫面變超大, </p>



<p class="wp-block-paragraph">努力地研究 tabulator 官方文件, 也看不出所以然:<br><a href="https://tabulator.info/docs/5.5/layout#fittowidth">https://tabulator.info/docs/5.5/layout#fittowidth</a></p>



<p class="wp-block-paragraph">手動調整 tabulator 的 table width:100% 也無解.</p>



<p class="wp-block-paragraph"><strong>產成的原因:</strong></p>



<p class="wp-block-paragraph">某一個爸爸 div 讓 tabulator 繼承到 display: grid;  而且上層又是用 flex, 交叉使用就掛掉.</p>



<p class="wp-block-paragraph">解法1: 避開 grid 就OK了. </p>



<p class="wp-block-paragraph">解法2: 在 tabulator 的上層設成 display: grid 居然也行, 真太神奇了, 呵呵. </p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2023/08/tabulator-width-overflow-hidden/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Left align and right align within div in Bootstrap</title>
		<link>https://stackoverflow.max-everyday.com/2023/07/left-align-and-right-align-within-div-in-bootstrap-2/</link>
					<comments>https://stackoverflow.max-everyday.com/2023/07/left-align-and-right-align-within-div-in-bootstrap-2/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Tue, 18 Jul 2023 10:04:52 +0000</pubDate>
				<category><![CDATA[css筆記]]></category>
		<category><![CDATA[Bootstrap]]></category>
		<category><![CDATA[css]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=4951</guid>

					<description><![CDATA[想把下面的按鈕們搬到右邊, 但都失敗, 成功後的...]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">想把下面的按鈕們搬到右邊, 但都失敗, 成功後的執行畫面:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="489" height="100" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2023/07/2023-07-18-17_59_38-Window.jpg" alt="" class="wp-image-4952"/></figure>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">解法:<br><a href="https://getbootstrap.com/docs/5.0/utilities/flex/">https://getbootstrap.com/docs/5.0/utilities/flex/</a></p>



<pre class="wp-block-code"><code>&lt;div class="d-flex justify-content-end"&gt;
  &lt;div class="mr-auto p-2"&gt;Flex item&lt;/div&gt;
  &lt;div class="p-2"&gt;Flex item&lt;/div&gt;
  &lt;div class="p-2"&gt;Flex item&lt;/div&gt;
&lt;/div&gt;</code></pre>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">直接下 <code>justify-content-end</code> , 沒有效果, </p>



<p class="wp-block-paragraph">使用 text-right 也失敗:<br><a href="https://getbootstrap.com/docs/4.0/utilities/text/">https://getbootstrap.com/docs/4.0/utilities/text/</a></p>



<pre class="wp-block-code"><code>&lt;p class="text-right">Right aligned text on all viewport sizes.&lt;/p></code></pre>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2023/07/left-align-and-right-align-within-div-in-bootstrap-2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>css selector tester online: jsoup</title>
		<link>https://stackoverflow.max-everyday.com/2023/07/css-selector-tester-online-jsoup/</link>
					<comments>https://stackoverflow.max-everyday.com/2023/07/css-selector-tester-online-jsoup/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Fri, 14 Jul 2023 18:10:17 +0000</pubDate>
				<category><![CDATA[css筆記]]></category>
		<category><![CDATA[css]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=4945</guid>

					<description><![CDATA[今天要分享一個跟css selector 有關的...]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">今天要分享一個跟css selector 有關的網站:<br><a href="https://try.jsoup.org/">https://try.jsoup.org/</a></p>



<p class="wp-block-paragraph">我實際執行畫面：</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="722" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2023/07/Screen-Shot-2023-07-15-at-2.07.07-AM-1024x722.png?v=1689358063" alt="" class="wp-image-4946" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2023/07/Screen-Shot-2023-07-15-at-2.07.07-AM-1024x722.png?v=1689358063 1024w, https://stackoverflow.max-everyday.com/wp-content/uploads/2023/07/Screen-Shot-2023-07-15-at-2.07.07-AM-600x423.png?v=1689358063 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2023/07/Screen-Shot-2023-07-15-at-2.07.07-AM-768x541.png?v=1689358063 768w, https://stackoverflow.max-everyday.com/wp-content/uploads/2023/07/Screen-Shot-2023-07-15-at-2.07.07-AM.png?v=1689358063 1375w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">原本的 css selector 是寫 tr.status_tr 但是，會連 Soldout 也一起被選到，改用 tr[class=&#8217;status_tr&#8217;] 就解決了，沒有使用到  :NOT().</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph">在網路上學習 css selector 的語法，想套用看看，例如我想試的是NOT 的用法：<br><a href="https://www.geeksforgeeks.org/how-to-use-a-not-equal-css-attribute-selector/">https://www.geeksforgeeks.org/how-to-use-a-not-equal-css-attribute-selector/</a></p>



<p class="wp-block-paragraph">相關討論：Can&#8217;t find a &#8220;not equal&#8221; css attribute selector<br><a href="https://stackoverflow.com/questions/25287229/cant-find-a-not-equal-css-attribute-selector">https://stackoverflow.com/questions/25287229/cant-find-a-not-equal-css-attribute-selector</a></p>



<p class="wp-block-paragraph">One problem with the accepted answer is that it will also select elements that do not have a&nbsp;<code>foo</code>&nbsp;attribute at all. Consider:</p>



<pre class="wp-block-code"><code>&lt;div&gt;No foo&lt;/div&gt;
&lt;div foo=""&gt;Empty foo&lt;/div&gt;
&lt;div foo="x"&gt;XXX&lt;/div&gt;
&lt;div foo="y"&gt;YYY&lt;/div&gt;
&lt;div foo="z"&gt;ZZZ&lt;/div&gt;
</code></pre>



<p class="wp-block-paragraph"><code>div:not([foo=''])</code>&nbsp;will select both the first and second&nbsp;<code>div</code>&nbsp;elements. If you only want&nbsp;<code>div</code>&nbsp;elements that have an attribute foo that is set to an empty string, you should use:</p>



<pre class="wp-block-code"><code>div&#91;foo]:not(&#91;foo=''])
</code></pre>



<p class="wp-block-paragraph">If you want all elements with attribute&nbsp;<code>foo</code>&nbsp;that is neither&nbsp;<code>y</code>&nbsp;nor&nbsp;<code>z</code>, you should use:</p>



<pre class="wp-block-code"><code>div&#91;foo]:not(&#91;foo='y']):not(&#91;foo='z'])
</code></pre>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2023/07/css-selector-tester-online-jsoup/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Bootstrap Tabs Example</title>
		<link>https://stackoverflow.max-everyday.com/2023/04/bootstrap-tab-wizard-example/</link>
					<comments>https://stackoverflow.max-everyday.com/2023/04/bootstrap-tab-wizard-example/#respond</comments>
		
		<dc:creator><![CDATA[max-stackoverflow]]></dc:creator>
		<pubDate>Tue, 18 Apr 2023 07:41:44 +0000</pubDate>
				<category><![CDATA[css筆記]]></category>
		<category><![CDATA[javascript筆記]]></category>
		<category><![CDATA[Bootstrap]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[javascript]]></category>
		<guid isPermaLink="false">https://stackoverflow.max-everyday.com/?p=4741</guid>

					<description><![CDATA[最近有一個需求, 想做成 wizard 風格的操...]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">最近有一個需求, 想做成 wizard  風格的操作界面, 首先是在 google 下 keyword:</p>



<pre class="wp-block-code"><code>bootstrap tabs template</code></pre>



<p class="wp-block-paragraph">使用下面的範例來修改:<br><a href="https://colorlib.com/etc/bwiz/colorlib-wizard-30/index.html">https://colorlib.com/etc/bwiz/colorlib-wizard-30/index.html</a></p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="977" height="656" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2023/04/2023-04-18-15_23_13-Window.jpg" alt="" class="wp-image-4742" srcset="https://stackoverflow.max-everyday.com/wp-content/uploads/2023/04/2023-04-18-15_23_13-Window.jpg?v=1681802647 977w, https://stackoverflow.max-everyday.com/wp-content/uploads/2023/04/2023-04-18-15_23_13-Window-600x403.jpg?v=1681802647 600w, https://stackoverflow.max-everyday.com/wp-content/uploads/2023/04/2023-04-18-15_23_13-Window-768x516.jpg?v=1681802647 768w" sizes="auto, (max-width: 977px) 100vw, 977px" /></figure>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">實做的結果:</p>



<p class="wp-block-paragraph">Step 1:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="505" height="384" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2023/04/2023-04-18-15_16_55-Window.jpg" alt="" class="wp-image-4743"/></figure>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Step 2:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="506" height="451" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2023/04/2023-04-18-15_17_44-Window.jpg" alt="" class="wp-image-4744"/></figure>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Step 3:</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="503" height="438" src="https://stackoverflow.max-everyday.com/wp-content/uploads/2023/04/2023-04-18-15_17_56-Window.jpg" alt="" class="wp-image-4745"/></figure>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">使用的 html:</p>



<pre class="wp-block-code"><code>&lt;div id="form-total" role="application" class="form-register wizard clearfix"&gt;
	&lt;div class="steps clearfix"&gt;
		&lt;ul role="tablist"&gt;
			&lt;li role="tab" aria-disabled="false" class="first current" aria-selected="true" id="your_table_nav_1"&gt;
				&lt;div&gt;
				&lt;span class="title"&gt;1&lt;/span&gt;&lt;/div&gt;
			&lt;/li&gt;
			&lt;li role="tab" aria-disabled="false" class="" aria-selected="true" id="your_table_nav_2"&gt;
				&lt;div&gt;
				&lt;span class="title"&gt;2&lt;/span&gt;&lt;/div&gt;
			&lt;/li&gt;
			&lt;li role="tab" aria-disabled="false" class="last" id="your_table_nav_3"&gt;
				&lt;div&gt;
				&lt;span class="title"&gt;3&lt;/span&gt;&lt;/div&gt;
			&lt;/li&gt;
		&lt;/ul&gt;
	&lt;/div&gt;

	&lt;div id="your_table_tab_1" class=""&gt;
                &lt;div class="col-12"&gt;
                  &lt;label for="your_table-field1-id" class="form-label"&gt;Field1&lt;/label&gt;
                    &lt;select class="form-select" aria-label="Default select" id="your_table-field1-id"&gt;
                    &lt;/select&gt;
                &lt;/div&gt;
	&lt;/div&gt;
	&lt;div id="your_table_tab_2" class="disappear"&gt;
                &lt;div class="col-12"&gt;
                  &lt;label for="your_table-field2-id" class="form-label"&gt;Field2&lt;/label&gt;
                    &lt;select class="form-select" aria-label="Default select" id="your_table-field2-id"&gt;
                    &lt;/select&gt;
                &lt;/div&gt;
                &lt;div class="col-12"&gt;
                  &lt;label for="your_table-field3-id" class="form-label"&gt;Field3&lt;/label&gt;
                    &lt;select class="form-select" aria-label="Default select" id="your_table-field3-id"&gt;
                    &lt;/select&gt;
                &lt;/div&gt;
	&lt;/div&gt;
	&lt;div id="your_table_tab_3" class="disappear"&gt;
                &lt;div class="row"&gt;
	                &lt;div class="col-3"&gt;
	                  &lt;label class="form-label"&gt;User&lt;/label&gt;
	                &lt;/div&gt;
	                &lt;div class="col"&gt;
	                  &lt;div id="your_table-user_name-confirm"&gt;&lt;/div&gt;
	                &lt;/div&gt;
                &lt;/div&gt;

                &lt;div class="row"&gt;
	                &lt;div class="col-3"&gt;
	                  &lt;label class="form-label"&gt;Field1&lt;/label&gt;
	                &lt;/div&gt;
	                &lt;div class="col"&gt;
	                  &lt;div id="your_table-field1-confirm"&gt;&lt;/div&gt;
	                &lt;/div&gt;
                &lt;/div&gt;

                &lt;div class="row"&gt;
	                &lt;div class="col-3"&gt;
	                  &lt;label class="form-label"&gt;Field2&lt;/label&gt;
	                &lt;/div&gt;
	                &lt;div class="col"&gt;
	                  &lt;div id="your_table-field2-confirm"&gt;&lt;/div&gt;
	                &lt;/div&gt;
                &lt;/div&gt;

                &lt;div class="row"&gt;
	                &lt;div class="col-3"&gt;
	                  &lt;label class="form-label"&gt;Field3&lt;/label&gt;
	                &lt;/div&gt;
	                &lt;div class="col"&gt;
	                  &lt;div id="your_table-field3-confirm"&gt;&lt;/div&gt;
	                &lt;/div&gt;
                &lt;/div&gt;
	&lt;/div&gt;

&lt;/div&gt;</code></pre>



<p class="wp-block-paragraph">下方的按鈕們:</p>



<pre class="wp-block-code"><code>&lt;button type="button" class="btn btn-secondary disappear" id='your_table-btn-previous_1' onclick="javascript:your_table_previous_1();"&gt;
	&lt;span&gt;Previous&lt;/span&gt;
&lt;/button&gt;

&lt;button type="button" class="btn btn-primary" id='your_table-btn-next_1' onclick="javascript:your_table_next_1();"&gt;
	&lt;span&gt;Next&lt;/span&gt;
&lt;/button&gt;

&lt;button type="button" class="btn btn-secondary disappear" id='your_table-btn-previous_2' onclick="javascript:your_table_previous_2();"&gt;
	&lt;span&gt;Previous&lt;/span&gt;
&lt;/button&gt;

&lt;button type="button" class="btn btn-primary" id='your_table-btn-next_2' onclick="javascript:your_table_next_2();"&gt;
	&lt;span&gt;Next&lt;/span&gt;
&lt;/button&gt;
</code></pre>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">使用的 css:</p>



<pre class="wp-block-preformatted"> .form-register .steps {
    margin-bottom: 33px;
    margin-top: 40px
}

.form-register .steps ul {
    display: flex;
    display: -webkit-flex;
    list-style: none;
    padding-left: 0;
    justify-content: center;
    -o-justify-content: center;
    -ms-justify-content: center;
    -moz-justify-content: center;
    -webkit-justify-content: center
}

.form-register .steps li,.form-register .steps li.current {
    outline: none;
    -o-outline: none;
    -ms-outline: none;
    -moz-outline: none;
    -webkit-outline: none
}

.form-register .steps li div {
    display: inline-block;
    width: 60px;
    height: 60px;
    border-radius: 50%;
    -o-border-radius: 50%;
    -ms-border-radius: 50%;
    -moz-border-radius: 50%;
    -webkit-border-radius: 50%;
    background: #ccc;
    margin-right: 143px;
    position: relative;
    outline: none
}

.form-register .steps li div::before {
    position: absolute;
    content: "";
    background: #e5e5e5;
    width: 143px;
    height: 2px;
    top: 50%;
    transform: translateY(-50%);
    -o-transform: translateY(-50%);
    -ms-transform: translateY(-50%);
    -moz-transform: translateY(-50%);
    -webkit-transform: translateY(-50%);
    left: 100%
}

.form-register .steps li.last div {
    margin-right: 0
}

.form-register .steps li.last div::before {
    content: none
}

.form-register .steps li.current div
,.form-register .steps li.current div:active
,.form-register .steps li.done div::before
,.form-register .steps li.done div
,.form-register .steps li.done div:active {
    background: #3760e5
}

.form-register .steps li .current-info {
    display: none
}

.form-register .steps li .title {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%,-50%);
    -o-transform: translate(-50%,-50%);
    -ms-transform: translate(-50%,-50%);
    -moz-transform: translate(-50%,-50%);
    -webkit-transform: translate(-50%,-50%);
    color: #fff;
    font-size: 24px;
    font-weight: 600;
    font-family: montserrat,sans-serif
}
</pre>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">使用到的 javascript:</p>



<p class="wp-block-paragraph">這段用來控制按鍵和區塊在切換時的顯示.</p>



<pre class="wp-block-code"><code>function switch_tab_step(table_name, active_at, tab_count) {
	for(let i=1; i&lt;=tab_count; i++){
		$("#"+ table_name +"_nav_"+i).removeClass("current");
		$("#"+ table_name +"_nav_"+i).removeClass("done");
		
		if(i&lt;active_at) {
			$("#"+ table_name +"_nav_"+i).addClass("done");
		}

		$("#"+ table_name +"_tab_"+i).addClass("disappear");

		$("#"+ table_name +"-btn-previous_"+i).addClass("disappear");
		$("#"+ table_name +"-btn-next_"+i).addClass("disappear");
	}

	$("#"+ table_name +"_nav_"+active_at).addClass("current");

	$("#"+ table_name +"_tab_"+active_at).removeClass("disappear");

	$("#"+ table_name +"-btn-previous_"+(active_at-1)).removeClass("disappear");
	$("#"+ table_name +"-btn-next_"+active_at).removeClass("disappear");
}</code></pre>



<p class="wp-block-paragraph">next 與 previous 的控制:</p>



<pre class="wp-block-code"><code>function your_table_next_1() {
	switch_tab_step('your_table',2,3);
}

function your_table_previous_1() {
	switch_tab_step('your_table',1,3);
}

function your_table_next_2() {
	switch_tab_step('your_table',3,3);
	
	// final step
    // your code here...
}

function your_table_previous_2() {
	switch_tab_step('your_table',2,3);
}</code></pre>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">大致上, 這樣就可以做出 wizard 效果.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://stackoverflow.max-everyday.com/2023/04/bootstrap-tab-wizard-example/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
