純 Css 實現 ui-layout 佈局

       年初,公司 UI 框架升級,幾番比較以後,layui 和 adminLte 同時入選。當然,很明顯,這倆框架都是師出 bootstrap,提供基礎的樣式、組件、插件。但要‘本土化’到項目中來,多少要再翻炒一遍。公司的系統頁,大多基於頁面高寬100%來開發作業,以前的佈局框架,無論是自己寫的,還是插件,如ui-layout,都是用腳本計算。
       現在,這倆新框架,柵格部分勉強算佈局的話,那就是他們的極限了,像例1這種簡單佈局,各個區域彈性佈局,中間區域超出滾動,翻遍這兩位文檔,都毫無建樹!

       如果更復雜點,分上下左右中五塊,在各區域內再上下左右佈局,那你不得瘋掉!

例1:


   

       可其實一想,自Css3出來後,這種用樣式都能解決的事,還引用插件,本身就反社會!用插件來佈局的時候,還要考慮加載數據和佈局腳本先後順序、頁面數據插入更新影響佈局等。    

 以前,大家都諾基亞用慣了,怕iphone(css3)是新生事物,有兼容問題,現在連買菜的師奶都用iphone (Css3)了,自然是再普通不過。

        對 ui-layout 有了解的都應該知道,ui-layout 一個能實現各區域的彈性佈局,其二是間隔條帶有切換開關(可設置各區默認顯示隱藏:如例2)。根據這兩條,我們試試用純 Css 做一個!

例2:

1,實現上下左右中佈局

測試中,上、下、左右、中分別對應div:header、footer、side、center

這個比較簡單,如下面代碼,但需留意 flex 這兩點:

1)、flex 子元素高寬塌陷,可參考 《Flex 子元素高度塌陷》

2)、像 .main這樣的佈局元素,無法設置高度,.main 加上 display:flex 再佈局,子元素 高度 100% 無效。

3)、flex 垂直佈局,IE失效,需要在 flex-grow:1 的子元素上,加 -ms-flex: 1 解決兼容!(不是 -ms-flex-grow

例3:

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<title>flex</title>
		<style>
			html{ height: 100%; } 
          	body,.layout{ display: flex; flex-direction: column;margin:0; height:100%; background: #fff; } 
          	.header{ height: 24px; line-height:24px; font-size: 14px; color: #333; background: #fff; border-bottom: 1px solid #11a3ee; } 
          	.main{ -ms-flex: 1; flex-grow: 1; display: flex; } 
          	.side,.header,.footer{padding: 10px; flex-shrink:0; } 
          	.side{ min-width: 200px; max-width: 40%;} 
          	.gap{ position: relative; width: 5px; cursor:pointer; margin: 0;background:#ddd; border-left: 1px solid #bbb; border-right: 1px solid #bbb; } 
          .center{flex-grow: 1; overflow:auto; } 
          .footer{ background:#e2e2e2; }
		</style>
	</head>
	<body>
		<div class="header">標題</div>
		<div class="main">
			<div class="side">west side</div>
			<div class="gap"></div>
			<div class="center"><div style="height: 800px;">center</div></div>
			<div class="gap"></div>
			<div class="side">east side</div>
		</div>
		<div class="footer">Copyright ©2018 Marc</div>
	</body>
</html>


 2、點擊間隔條,顯示隱藏相關區域

純css的切換,可能你馬上想到純Css選項卡:利用 錨點label + radio,道理差不多,但這裏都用不到,而且個人希望.gap只能是一個標籤,加一堆標籤,開發上哪海底撈去。

這裏要考慮兩個問題:
1)、.gap 怎樣做成一個切換按鈕?
2)、代碼,.gap只能放切換side前(例4),但頁面呈現,又必須在side後。

.gap:checked + .side{ display: none }

gap:checked + side,因爲相鄰選擇器只能選擇後面的元素 

例 4:

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<title>flex</title>
		<style>
			html{ height: 100%; } 
          	body,.layout{ display: flex; flex-direction: column;margin:0; height:100%; background: #fff; } 
          	.header{ height: 24px; line-height:24px; font-size: 14px; color: #333; background: #fff; border-bottom: 1px solid #11a3ee; } 
          	.main{ -ms-flex: 1; flex-grow: 1; display: flex; } 
          	.side,.header,.footer{ padding: 10px; flex-shrink:0; } 
            .side{ min-width: 200px; max-width: 40%;} 
            .gap{ position: relative; width: 5px; cursor:pointer; margin: 0; background:#ddd; border-left: 1px solid #bbb; border-right: 1px solid #bbb; } 
            .center{ flex-grow: 1; overflow:auto; } 
            .footer{ background:#e2e2e2; }
		</style>
	</head>
	<body>
		<div class="header">標題</div>
		<div class="main">
			<div class="gap"></div>
			<div class="side">west side</div>
			<div class="center"><div style="height: 800px;">center</div></div>
			<div class="gap"></div>
			<div class="side">east side</div>
		</div>
		<div class="footer">Copyright ©2018 Marc</div>
	</body>
</html>

.gap 做成一個切換,這個問題困擾我很久,翻來覆去,發現能用的、最合適的也就 checkbox 了,能切換、又能默認設置關閉隱藏,如例5:成功切換 side!

例5:

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<title>flex</title>
		<style>
			html{ height: 100%; } 
          	body,.layout{ display: flex; flex-direction: column;margin:0; height:100%; background: #fff; } 
          	.header{ height: 24px; line-height:24px; font-size: 14px; color: #333; background: #fff; border-bottom: 1px solid #11a3ee; } 
          	.main{ -ms-flex: 1; flex-grow: 1; display: flex; } 
          	.side,.header,.footer{padding: 10px; flex-shrink:0; }
          	.side{ min-width: 200px; max-width: 40%;} 
          	.gap{ cursor:pointer; margin: 0; } 
          	.gap:checked + .side{ display: none; } 
          	.center{ flex-grow: 1; overflow:auto; } 
          	.footer{ background:#e2e2e2;}
		</style>
	</head>
	<body>
		<div class="header">標題</div>
		<div class="main">
			<input type="checkbox" class="gap" title="切換" />
			<div class="side">west side</div>
			<div class="center"><div style="height: 800px;">center</div></div>
			<input type="checkbox" class="gap" title="切換" />
			<div class="side">east side</div>
		</div>
		<div class="footer">Copyright ©2018 Marc</div>
	</body>
</html>

不用管checkbox 大小,先解決問題2:左邊區域的 gap 跑到  side 前面了,但頁面裏,gap 需要顯示 在 side 後面,怎麼辦?

也就是排序問題,如果仔細研究過 flex,你應該知道 flex 有個屬性 叫 order,沒錯,用 order 來排序!試一試!

柳暗花明,最黑暗處照進一道光,如此,美妙!


例6:

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<title>flex</title>
		<style>
			html{ height: 100%; } 
          	body,.layout{ display: flex; flex-direction: column; margin:0; height:100%; background: #fff; } 
          	.header{ height: 24px; line-height:24px; font-size: 14px; color: #333; background: #fff; border-bottom: 1px solid #11a3ee; } 
          	.main{ -ms-flex: 1; flex-grow: 1; display: flex; } 
          	.side,.header,.footer{ padding: 10px; flex-shrink:0; } 
          	.side{ min-width: 200px; max-width: 40%;} 
          	.gap{ cursor:pointer; margin: 0; } 
          	.gap:checked + .side{ display: none;} 
          	.center{ flex-grow: 1; overflow:auto; } 
          	.footer{ background:#e2e2e2;} 
          	.main>.side:nth-of-type(1){ order:1; } 
          	.main>.gap:nth-child(1){ order:2;} 
          	.center,.center+.gap,.center+.gap+.side{ order:3; }
		</style>
	</head>
	<body>
		<div class="header">標題</div>
		<div class="main">
			<input type="checkbox" class="gap" title="切換" />
			<div class="side">west side</div>
			<div class="center"><div style="height: 800px;">center</div></div>
			<input type="checkbox" class="gap" title="切換" />
			<div class="side">east side</div>
		</div>
		<div class="footer">Copyright ©2018 Marc</div>
	</body>
</html>

 

最後,checkbox大小的問題!

只有花生米大小,高寬又無法更改(千萬別出加:zoom 或 transform:scale(1w)這種餿主意),讓我曾反反覆覆多次放棄 checkbox,去需求其他出口,未果,只好硬着頭皮回來,地毯式搜索一個個屬性嘗試!因爲要滿足以下三個條件:

1)、只能在 gap 內加標籤,最好只有 gap 一個標籤!不接受外面再加標籤: label 

<label for="side"></label>	
<input type="radio" id="side" class="gap">
<div class="side"></lable>

2)、gap 要實現高100%,但又不能影響功能實現

<label for="side" class="gap"><input type="radio" id="side"></label>
<div class="side"></lable>

3)、.main 由於沒有設置高度,子元素在 不脫離文檔流(position:static、position:relative) 的情況下100% 無效,絕對定位,100%有效,但 gap 定位的top、left 都不確定!

 

最後嘗試到一個神奇的方法,要實現這個方法,先實現 gap 高100% :main內加了個高100%的標籤(wrap)

這個神奇的方法呢,就是僞類!給 gap 加僞類,用僞類的100%高做門面。神奇的是,點擊僞類層 ,checkbox 切換一樣絲般順滑!有意思!

例7:IE支持10及以上版本

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<title>flex</title>
		<style>
			html{ height: 100%; } 
          	body,.layout{ display: flex; flex-direction: column;margin:0; height:100%; background: #fff; } 
          	.header{ height: 24px; line-height:24px; font-size: 14px; color: #333; background: #fff; border-bottom: 1px solid #11a3ee; } 
          	.main{ -ms-flex: 1; flex-grow: 1; position: relative; } 
          	.wrap{ position:absolute; display: flex; width: 100%; height: 100%; } 			 
            .side,.header,.footer{padding: 10px; flex-shrink:0; }
          	.side{ min-width: 200px; max-width: 40%;} 
          	.gap{ position: relative;box-sizing: border-box;margin: 0;width: 10px;height: 100%;background: #ddd;border-left: 1px solid #bbb;border-right: 1px solid #bbb;cursor:pointer; } 
          	.gap:after{ position: absolute; top:0; right: 0; left: 0; bottom:0; content: ""; background: #ddd; border-left: 1px solid #bbb; border-right:1px solid #bbb; } 
          	.gap:checked + .side{ display: none; } 
            .center{ flex-grow:1; overflow:auto; } 
          	.footer{ background:#e2e2e2; } 
          	.wrap>.side:nth-of-type(1){order:1; } 
          	.wrap>.gap:nth-child(1){ order:2; } 
          	.center,.center+.gap,.center+.gap+.side{order:3; }
		</style>
	</head>
	<body>
		<div class="header">標題</div>
		<div class="main">
			<div class="wrap">
				<input type="checkbox" class="gap" title="切換" />
				<div class="side">west side</div>
				<div class="center"><div style="height: 800px;">center</div></div>
				<input type="checkbox" class="gap" title="切換" checked="checked" />
				<div class="side">east side</div>
			</div>
		</div>
		<div class="footer">Copyright ©2018 Marc</div>
	</body>
</html>

到此,順利實現了!說的有些囉嗦了!我在公司項目中,暫時只用佈局部分。
最後,留個問題,input來做切換、多加的那層wrap標籤,是否可以再優化呢!希望你有更好的方法!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章