当浏览器应用一个用户交互界面时, 一种很好的方式是可以最小化差异和问题, UI 是可预测的. 想要追踪到所有的差异是比较困难的, 所以我将这些共同问题整理成一个列表, 为你在做新项目时提供一个简单易用的参考指南.
1. 重置 button 和 input 元素的背景
当我们添加 button 时, 重置 button 的背景, 或者在不同浏览器上展示不一样. 下面这个例子中展示了相同的 button 在 Chrome 和 Safari 的效果, 后者默认有一个灰色的背景.
重置 button 的背景就可以解决这个问题.
- button {
- appearance: none;
- background: transparent;
- /* Other styles */
- }
- 2.Overflow: scroll vs. auto
要限制元素的高度来让用户在元素内滑动, 需要给该元素添加 overflow: scroll-y. 在 macOS 系统的 Chrome 上看起来还好, 但是在 Windows 系统的 Chrome 上滚动条会一直存在 (即使内容很少). 这是因为 scroll-y 不管内容的多少都会显示一个滚动条, 而 overflow: auto 只有在需要的时候才会显示滚动条.
- .element {
- height: 300px;
- overflow-y: auto;
- }
3. 添加 flex-wrap
想让一个元素显示成一个 flex 容器, 只需要简单地加上 display: flex. 然而, 如果没有设置 flex-wrap, 当屏幕尺寸变小时, 浏览器会显示成水平方向的滚动条.
- <div class="wrapper">
- <div class="item"></div>
- <div class="item"></div>
- <div class="item"></div>
- <div class="item"></div>
- <div class="item"></div>
- <div class="item"></div>
- </div>
- .wrapper {
- display: flex;
- }
- .item {
- flex: 0 0 120px;
- height: 100px;
- }
上面这个例子在大屏幕上显示的正常, 在手机端会显示一个横向的滚动条. 下图中, 左边显示一个横向的滚动条, 且子元素没有被包裹; 右边的子元素被包裹成两行.
解决方案很简单, 包裹容器应该知道什么时候没有空隙, 这时就要让子元素换行.
- .wrapper {
- display: flex;
- flex-wrap: wrap;
- }
4. 不要在 flex item 个数是动态的时候使用 justify-content: space-between
当一个 flex 容器应用 justify-content: space-between 时, 它会分散元素, 并为它们分配一个相同的间距. 我们的例子有八个卡片元素, 它们看起来显示很正常. 但是当我们的子元素是七个呢? 第二行的元素看起来会和第一行不一样. 下图分别是八个元素和七个元素显示的效果.
这种情况下, 用 CSS grid 会更合适.
5. 长字符串和链接
当一个文章在手机屏幕上显示的时候, 一个长的词或链接也许会引起横向滚动条的出现. 使用 CSS 的 Word-break 可以防止这种情况产生.
- .article-content p {
- Word-break: break-all;
- }
6. 透明渐变
当添加一个由透明色开始或结束的渐变, 在 Safari 上看起来像黑色的, 因为 Safari 不识别关键字 transparent. 下图中分别是 Chrome 70 和 Safari 12.
- .section-hero {
- background: linear-gradient(transparent, #d7e0ef), #527ee0;
- /*Other styles*/
- }
使用 rgba(0, 0, 0, 0) 替换, 就会像正常的显示.
- .section-hero {
- background: linear-gradient(rgba(0, 0, 0,0), #d7e0ef), #527ee0;
- /*Other styles*/
- }
7.CSS Grid 中 auto-fit 和 auto-fill 区别的误解
在 CSS Grid 中, repeat 函数不需要使用媒体查询就可以创建一个响应式列布局. 为了实现这个效果, 需要使用 auto-fill 或 auto-fit.
- .wrapper {
- grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
- }
简单地说, auto-fill 会整理这些列而不会拓展它们的宽度, 而 auto-fit 只在没有空的列时才将它们的宽度置为 0.Sara Soueidan 写了一篇关于这个话题很不错的文章.
8. 当 viewport 不够高时, 将元素固定在屏幕顶部
如果你把一个元素固定在屏幕顶部, 当 viewport 不够高时会发生什么呢? 很简单, 它会占用屏幕空间, 结果是垂直方向浏览网站的可用空间会变小, 看着很不舒服, 很大程度降低了用户体验.
- @media (min-height: 500px) {
- .site-header {
- position: sticky;
- top: 0;
- /*other styles*/
- }
- }
上面这段代码, 可用让浏览器在 viewport 高度大于等于 500px 的时候才将 header 固定到顶部. 同样重要的是, 只有声明了 top 属性之后, position: sticty 才会起作用.
9. 为图片设置 max-width
当添加一个图片时, 定义 max-width: 100%, 这样当屏幕小的时候, 图片可以自适应尺寸. 否则, 浏览器就会显示一个横向的滚动条.
- img {
- max-width: 100%;
- }
10. 使用 CSS Grid 来定义 main 和 aside 元素
CSS grid 可以用来定义一个布局中的 main 和 aside 块, 这是 grid 中的一个完美的用处. 这种布局的结果是, aside 块的高度会和 main 元素的高度一致, 即使 main 元素是空的.
为了解决这个问题, 将 aside 元素与父元素的开始对齐, 这样它的高度就不会扩大.
- .wrapper {
- display: grid;
- grid-template-columns: repeat(12, minmax(0, 1fr));
- grid-gap: 20px;
- }
- /* align-self 会告诉 adise 元素, 让它跟父元素的开始对齐 */
- aside {
- grid-column: 1 / 4;
- grid-row: 1;
- align-self: start;
- }
- main {
- grid-column: 4 / 13;
- }
11. 给 SVG 添加 fill
有时在使用 SVG 时, 如果 SVG 已经内联声明了 fill 属性, CSS 里的 fill 就不会正常工作了. 要解决这个问题, 要么去掉 SVG 的 fill 属性, 要么覆盖 fill: color.
- .some-icon {
- fill: #137cbf;
- }
如果 SVG 定义了 fill 属性, 上面这个不会起作用. 应该用下面这个替换掉.
- .some-icon path {
- fill: #137cbf;
- }
12. 使用伪元素
任何可以使用伪元素的时候, 我都会使用它. 它为我们提供了一种创建多数情况是为了装饰作用的伪元素的方法, 而不需要添加真的 html.
在使用它时, 开发者可能会忘了做下面这些事:
添加 content: "" 属性;
不定义 display 时, 设置 width 和 height.
下面的例子中, 有一个标题使用伪元素作为标记. 应该添加 content: "" 属性, 而且为了让 width 和 height 起作用, 还需要设置 display: inline-block.
13. 使用 display: inline-block 时, 诡异的间距
将两个或多个元素设置成 display: inline-block 或 display: inline 会让每两个元素间创建一个小空白. 这个小空白是由于浏览器将这些元素解析成字, 在它们之间添加一个字符的空白.
下面例子中, 每个元素在右侧有一个 8px 的空白, 但是由于设置了 display: inine-block, 这个空白变成了 12px.
- li:not(:last-child) {
- margin-right: 8px;
- }
一个简单的解决方法, 是对父元素设置 font-size: 0, 再单独对子元素设置字体大小.
- ul {
- font-size: 0;
- }
- li {
- font-size: 16px;
- }
14. 当一个 label 标签映射到一个输入框时, 为它设置 for="ID"
当使用 form 元素时, 确保所有的 label 元素都有一个映射的 ID. 这可以让它们更易理解, 当它们被点击时, 相关联的输入框会获得焦点.
- <label for="emailAddress">
- Email address:
- </label>
- <input type="email" id="emailAddress">
15. 在交互性 HTML 元素上字体不起作用
当字体关联到整个文档, 它们不会被应用到 input,button,select 和 textarea 等这些元素上. 它们不会继承默认值, 因为浏览器会将系统默认字体应用到它们上面.
为了解决这个问题, 需要手动设置字体属性.
- input, button, select, textarea {
- font-family: your-awesome-font-name;
- }
16. 水平滚动条
由于一些元素的宽度, 会产生横向的滚动条. 发现这个问题原因最简单的方法是用 CSS 轮廓线. Addy Osmani 分享了一个很简单的监本来向浏览器控制台为页面每个元素添加轮廓线.
- [].forEach.call($$("*"), function(a) {
- a.style.outline =
- "1px solid #" + (~~(Math.random() * (1 <<24))).toString(16);
- });
17. 压缩或拉伸图片
当你在 CSS 中改变一个图片的大小, 如果没有设置宽高的话, 图片的大小会被压缩或拉伸. 解决方法很简单, 就是使用 CSS 的 object-fit, 它的实用性跟背景图片的 background-size: cover 很类似.
- img {
- object-fit: cover;
- }
使用 object-fit 不是所有场景下最好的解决方法. 一些图片展示的时候不需要裁剪或改变大小, 还有一些平台会强制用户按照设定好的尺寸上传或裁剪图片.
18. 为 input 添加正确的 type
为 input 字段使用正确的 type, 可以改善手机浏览器端的用户体验, 对用户更加友好.
- <form action="">
- <p>
- <label for="name">Full name</label>
- <input type="text" id="name">
- </p>
- <p>
- <label for="email">Email</label>
- <input type="email" id="email">
- </p>
- <p>
- <label for="phone">Phone</label>
- <input type="tel" id="phone">
- </p>
- </form>
上面这段代码, 在手机上各个输入框获取焦点时展示的效果.
19. 从右向左布局的手机号码
当在一个从右向左布局中添加 +972-123555777 这样的手机号码时, 加号会被定位到数字的末尾. 要解决这个问题, 再给手机号码分配一个方向.
- p {
- direction: ltr;
- }
结论
上面提到的问题是我在前端开发工作中遇到过的一些相同的问题, 我的目标是要在做新的 web 项目时, 保留一个规律的列表.
来源: https://juejin.im/entry/5c502305e51d453f4561508b