各位好,欢迎来到今天的“CSS Environment Variables & Safe Area Insets” 讲座。今天咱们就一起扒一扒CSS这位老兄的新玩具,看看它能玩出什么花样,尤其是跟那些“安全区域”搅和在一起的时候。准备好了吗?咱们这就开始!
开场白:CSS 的“环境意识”觉醒
话说CSS一直以来都像个专注的艺术家,埋头苦干,只管把样式画出来,至于它画在什么环境里,那可不管。但时代变了,现在是响应式设计的天下,CSS也得有点“环境意识”才行。 这就引出了咱们今天的主角之一:env()
函数,还有它的小伙伴 safe-area-inset-*
。
第一部分:env()
函数:CSS 的千里眼
env()
函数,顾名思义,就是用来读取“环境变量”的。这里的“环境变量”不是指操作系统里的那些,而是由浏览器或者宿主环境(比如你的App WebView)提供的一些信息。
-
语法:
property: env(variable-name, fallback-value);
variable-name
:你要读取的环境变量的名字。fallback-value
:可选参数,如果环境变量不存在,就用这个值。 就像你问别人借钱,最好先想好如果借不到怎么办。
-
例子:
body { background-color: env(theme-color, white); /* 如果有theme-color就用它,没有就用白色 */ }
这个例子里,如果浏览器或者宿主环境定义了
theme-color
这个环境变量,那么body
的背景色就会是那个颜色。否则,就是白色。 -
浏览器支持:
env()
的浏览器支持情况还算不错,但也不是所有浏览器都支持。使用前最好查一下 Can I Use,或者用@supports
特性查询来做兼容性处理。@supports (background-color: env(safe-area-inset-top)) { /* 只有在支持 env() 的浏览器里才执行这里的代码 */ body { padding-top: env(safe-area-inset-top); } }
*第二部分:`safe-area-inset-`:那些年,我们躲过的刘海**
现在,重头戏来了!safe-area-inset-*
是一组预定义的环境变量,专门用来获取“安全区域”的信息。
-
什么是安全区域?
简单来说,安全区域就是屏幕上没有被系统UI元素(比如状态栏、导航栏、刘海、虚拟按键)遮挡的区域。 想象一下,你的手机屏幕上有个刘海,或者底部有个虚拟按键栏,你的内容要显示在这些东西的“安全范围”之内,才不会被遮住。
-
*`safe-area-inset-` 变量:**
变量名 含义 safe-area-inset-top
安全区域距离屏幕顶部的距离。 safe-area-inset-right
安全区域距离屏幕右侧的距离。 safe-area-inset-bottom
安全区域距离屏幕底部的距离。 safe-area-inset-left
安全区域距离屏幕左侧的距离。 这些变量的值都是长度值,比如
px
,em
,rem
等。 -
用法示例:
body { padding-top: env(safe-area-inset-top, 0px); /* 顶部安全区域的内边距 */ padding-right: env(safe-area-inset-right, 0px); /* 右侧安全区域的内边距 */ padding-bottom: env(safe-area-inset-bottom, 0px); /* 底部安全区域的内边距 */ padding-left: env(safe-area-inset-left, 0px); /* 左侧安全区域的内边距 */ } .container { position: fixed; bottom: 0; left: 0; width: 100%; padding-bottom: calc(env(safe-area-inset-bottom, 0px) + 10px); /* 底部固定定位元素的内边距,加上10px的额外间距 */ }
上面的例子里,我们给
body
加上了安全区域的内边距,这样内容就不会被状态栏或者刘海遮挡了。 还有一个例子是给底部固定定位的元素加上内边距,保证它不会被虚拟按键栏遮挡,并且额外增加了10px的间距。 -
constant()
函数(已废弃):在
env()
出现之前,iOS Safari 提供了一个类似的函数叫做constant()
,用来获取安全区域的信息。 但是constant()
已经被废弃了,现在应该使用env()
和safe-area-inset-*
。- 注意: 不要再使用
constant()
了!
- 注意: 不要再使用
第三部分:实战演练:打造安全感满满的页面
光说不练假把式,咱们来几个实际的例子,看看怎么用 env()
和 safe-area-inset-*
来打造安全感满满的页面。
-
场景一:全屏图片
假设你有一个全屏显示的图片,但是不想让它被状态栏或者刘海遮挡。
<!DOCTYPE html> <html> <head> <title>全屏图片</title> <style> body { margin: 0; height: 100vh; /* 确保 body 占据整个视口高度 */ overflow: hidden; /* 隐藏滚动条 */ } .full-screen-image { width: 100%; height: 100%; object-fit: cover; /* 保持图片宽高比并填充整个容器 */ padding-top: env(safe-area-inset-top, 0px); /* 关键:顶部安全区域内边距 */ padding-bottom: env(safe-area-inset-bottom, 0px); /* 底部安全区域内边距 */ } </style> </head> <body> <img class="full-screen-image" src="your-image.jpg" alt="全屏图片"> </body> </html>
在这个例子里,我们给
img
元素加上了顶部和底部的安全区域内边距,这样图片就不会被状态栏或者刘海遮挡了。object-fit: cover;
保证了图片能够填充整个容器,并且保持宽高比。 -
场景二:固定底部导航栏
假设你有一个固定在底部的导航栏,但是不想让它被虚拟按键栏遮挡。
<!DOCTYPE html> <html> <head> <title>底部导航栏</title> <style> body { margin: 0; padding-bottom: 50px; /* 预留底部导航栏的空间 */ } .bottom-nav { position: fixed; bottom: 0; left: 0; width: 100%; height: 50px; background-color: #f0f0f0; display: flex; justify-content: space-around; align-items: center; padding-bottom: env(safe-area-inset-bottom, 0px); /* 关键:底部安全区域内边距 */ } .bottom-nav a { text-decoration: none; color: #333; } </style> </head> <body> <h1>Some Content</h1> <p>More Content...</p> <nav class="bottom-nav"> <a href="#">Home</a> <a href="#">Search</a> <a href="#">Profile</a> </nav> </body> </html>
在这个例子里,我们给
nav
元素加上了底部的安全区域内边距,这样导航栏就不会被虚拟按键栏遮挡了。 同时,我们给body
预留了 50px 的底部空间,避免内容被导航栏覆盖。 -
场景三:聊天气泡
很多聊天应用的气泡会贴着屏幕底部显示,如果底部有虚拟按键,就需要考虑安全区域。
.chat-bubble { position: absolute; bottom: 10px; left: 10px; background-color: #eee; padding: 10px; border-radius: 10px; margin-bottom: env(safe-area-inset-bottom, 0px); /* 底部安全区域外边距,避免被虚拟按键遮挡 */ }
这样,聊天气泡就会自动避开底部虚拟按键区域,保证用户体验。
第四部分:注意事项和高级技巧
-
viewport-fit=cover
:要让
safe-area-inset-*
生效,需要在<meta>
标签里设置viewport-fit=cover
。<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
viewport-fit=cover
会让网页内容充满整个屏幕,包括安全区域。 如果不设置这个,safe-area-inset-*
的值可能都是 0。 -
配合
calc()
使用:safe-area-inset-*
的值可以和其他长度值进行计算,比如:.element { padding-top: calc(env(safe-area-inset-top, 0px) + 20px); /* 顶部安全区域内边距加上20px */ }
-
动态更新:
安全区域的值可能会动态变化,比如用户旋转屏幕,或者显示/隐藏虚拟按键。 所以,最好使用 CSS 变量,并用 JavaScript 来更新这些变量的值。
function updateSafeAreaVariables() { document.documentElement.style.setProperty('--safe-area-top', `${window.safeAreaInsets.top}px`); document.documentElement.style.setProperty('--safe-area-bottom', `${window.safeAreaInsets.bottom}px`); document.documentElement.style.setProperty('--safe-area-left', `${window.safeAreaInsets.left}px`); document.documentElement.style.setProperty('--safe-area-right', `${window.safeAreaInsets.right}px`); } window.addEventListener('resize', updateSafeAreaVariables); updateSafeAreaVariables(); // 初始化时也调用一次
然后在 CSS 中使用这些变量:
body { padding-top: env(--safe-area-top, 0px); padding-bottom: env(--safe-area-bottom, 0px); padding-left: env(--safe-area-left, 0px); padding-right: env(--safe-area-right, 0px); }
注意: 上面的
window.safeAreaInsets
只是一个示例,具体的 API 取决于你的宿主环境(比如 WebView)。 -
测试:
在不同的设备和浏览器上进行测试,确保你的页面在各种情况下都能正常显示。 可以使用浏览器开发者工具的“设备模式”来模拟不同的屏幕尺寸和设备。
-
优雅降级:
由于
env()
和safe-area-inset-*
的浏览器支持情况不一致,要做好优雅降级。 可以使用fallback-value
或者@supports
特性查询来提供备用方案。body { padding-top: env(safe-area-inset-top, 20px); /* 如果不支持,就用20px的内边距 */ } @supports not (padding-top: env(safe-area-inset-top)) { body { padding-top: 20px; /* 如果完全不支持 env(),就用20px */ } }
第五部分:总结与展望
今天咱们一起学习了 CSS 的 env()
函数和 safe-area-inset-*
变量,了解了它们的作用、用法和注意事项。 它们是现代 Web 开发中非常重要的工具,可以帮助我们打造更好的用户体验,让我们的页面在各种设备上都能完美显示。
随着 Web 技术的不断发展,CSS 也会变得越来越强大, 相信未来会有更多的“环境变量”出现, 让我们拭目以待!
结束语:
感谢大家的聆听,希望今天的讲座对你有所帮助。 如果你还有任何问题,欢迎随时提问。 下次再见!