纯 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标签,是否可以再优化呢!希望你有更好的方法!

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