利用純 CSS3 做出自適應的 lightbox

因為工作需求,要做一個使用說明頁。但「使用說明」並非這個案子的主要需求,所以決定利用 Lightbox 取代多做一頁 HTML,但使用功能強大的 Lightbox plugin 有些大材小用,所以思考了一下,決定使用純 CSS3 寫一個簡單、又能自適應的 Lightbox。

關於「純 CSS」到底有什麼好處?這邊就不再贅述了,簡單好上手、讀取速度快算是兩大特點;雖然不是所有瀏覽器都支援 CSS3,但我這個案子是應用在手機上,基本上沒有手機不支援 CSS3,所以不用太過擔心這方面的需求。

以下先放上範例讓大家試玩,點選按鈕「Click Me」或者是旁邊的圖片,都可以看到 Lightbox 的效果喲!

See the Pen sbwmf by MUKi (@mukiwu) on CodePen.

喜翻嗎?有興趣想實作嗎?以下跟大家分享我的實作經驗囉!


HTML 結構

要製作純 CSS 的 Lightbox 並不難,我們先從 HTML 開始寫起吧!
關於點擊後,要展開哪個 Lightbox?只需利用相同的id名稱即可做到。此外重點只有三個元件,分別為:

  • 打開 Lightbox 的元件(例如按鈕、圖片)
  • Lightbox 展開後的內容
  • 關閉 Lightbox 的元件

所以 HTML 結構可以這麼寫:

<body>

<section>
  Click Me
</section>

<div class="lightbox-target" id="notice">
  <div class="content">
    hello world<br />Hello World
  </div>
  
</div>

</body>

這邊特地帶出body標籤,是要提醒大家,請把lightbox-target(Lightbox 展開後的內容)拉出來,寫在body的子層。

大家可以想像一下,正常點選 Lightbox 後,整個螢幕都會黑掉,Lightbox 會出現在螢幕的正中央才是正確的。如果將lightbox-target包在任何的div裡,就會受到該div的定位或寬度限制,讓你的 Lightbox 位置變得很詭異。

如果看不太懂沒關係,讓我們做成圖解吧!

▼ 正常的 Lightbox
▼ 錯位的 Lightbox

因為我們會利用lightbox-target製作透明的覆蓋底層,所以透過圖解,應該可以清楚了解他們的差異吧!總之lightbox-target的位置會影響到整個版面就對了 XD

以上就是 Lightbox 的 HTML 結構,接下來要使用 CSS 做出 Lightbox 的展開與關閉。


CSS 樣式與寫法

樣式的部分,會分成以下幾個區塊:

  • lightbox-target:Lightbox 的黑底背景,即俗稱的 overlay
  • content以及img:設定跳出 Lightbox 時,出現的內容或圖片樣式
  • lightbox-target:target:我們利用:target設定當「點選的元件變為目標時」,會出現的 CSS 樣式。
  • lightbox-close:關閉 Lightbox 的「X」樣式。

可以參考我的 CSS 寫法(我有在裡面加上註解,大家可以參考相關註解歐):

.lightbox-target {
	/* 設定好背景層的樣式以及位置 */
	position: fixed;
	top: -100%;
	width: 100%;
	background: rgba(0,0,0,.7);

	/* 預設透明度為 0,觸發 :target 後,利用動畫效果調整透明度 */
	opacity: 0;
	@include transition(opacity .5s ease-in-out);
	overflow: hidden;
	.content {
		/* 設定內容的樣式及位置(白底區塊) */
		width: 90%;
		height: 90%;
		background: #fff;
		color: #333;
		margin: auto;
		position: absolute;
		top: 0;
		left: 0;
		right: 0;
		bottom: 0;
		border: 3px solid #fff;
		@include box-shadow(0 0 8px rgba(0,0,0,.3));
		box-sizing: border-box;

		/* 預設寬高為 0,觸發 :target 後,利用動畫效果展開寬與高 */
		max-height: 0%;
		max-width: 0%;
		@include transition(.5s ease-in-out);
	}
	img {
		/* 設定圖片的樣式及位置,利用 */
		margin: auto;
		position: absolute;
		top: 0;
		left: 0;
		right: 0;
		bottom: 0;
		border: 3px solid #fff;
		@include box-shadow(0 0 8px rgba(0,0,0,.3));
		box-sizing: border-box;

		/* 預設寬高為 0,觸發 :target 後,利用動畫效果展開寬與高 */
		max-height: 0%;
		max-width: 0%;
		@include transition(.5s ease-in-out);
	}

	/* 當 :target 觸發後,index-target 的透明度為 1;content &amp; img 的寬高為 100% */
	&amp;:target {
		opacity: 1;
		top: 0;
		bottom: 0;
		.content, img {
			max-height: 100%;
			max-width: 100%;
		}
		.lightbox-close {
			top: 5%;
		}
	}
}

/* 關閉 Lightbox 按鈕的位置及樣式 */
.lightbox-close {
	display: block;
	width: 50px;
	height: 50px;
	box-sizing: border-box;
	background: #139dd7;
	color: #fff;
	position: absolute;
	top: 10%;
	right: 5%;
	@include transition(.5s ease-in-out);

	/* 利用偽元素做出 \ 以及 / 的線條,合併就變成 X 囉 */
	&amp;:before, &amp;:after {
		content: " ";
		display: block;
		height: 30px;
		width: 1px;
		background: #fff;
		position: absolute;
		left: 26px;
		top: 10px;
		@include transform(rotate(45deg));
	}
	&amp;:after {
		@include transform(rotate(-45deg));
	}
}

利用 HTML 跟 CSS 就可以很快速的做出簡易的 Lightbox 囉,而且可以支援 HTML,或是單純的展示圖片,非常好用呢!!!
最後放上整頁的 DEMO 給大家參考,應該會更有畫面!

有興趣的朋友,也可以自行修改 Lightbox 的樣式,讓他更符合每個網站的需求 🙂


  • Mark

    Uncaught TypeError: Cannot read property ‘split’ of undefined 有個js小錯誤

    • 好的,我等等來看一下是什麼問題

  • 極爺

    請問一下 css 能做到 overlay 可以按一下便關閉整個燈箱嗎??

    • 你可以自由調整 lightbox-close 的大小,就可以做出你說的那個效果了。

  • Tseng Yu

    您好:我一直無法做出來@@ 我一直按Click Me 也無法, 就算我做好了連結 他還是一樣不能跑出來

    • 你好,我有附上 codepen 連結,裡面有完整的語法,你可以先對照一下是哪裡有問題喔