【CSS in Depth 2 精译】2.3 告别像素思维

当前内容所在位置

  • 第一章 层叠、优先级与继承
  • 第二章 相对单位
    • 2.1 相对单位的威力
      • 2.1.1 响应式设计的兴起
    • 2.2 em 与 rem
      • 2.2.1 使用 em 定义字号
      • 2.2.2 使用 rem 设置字号
    • 2.3 告别像素思维 ✔️
    • 2.4 视口的相对单位
    • 2.5 无单位的数值与行高
    • 2.6 自定义属性
    • 2.7 本章小结

2.3 告别像素思维

过去常见的一种设计样式的做法(pattern),更准确地说是反常规的做法(antipattern),是将页面根元素的字号设为 0.625em62.5%;于是浏览器的默认字号就从 16px 缩小到了 10px。这种做法看似简化了数学运算——当设计师说字号为 14px,您只要在心中轻松除以 10,再让字号为 1.4rem 即可,顺便还兼顾了相对单位,例如:

html {
  font-size: 0.625em;
}

但我不推荐这样做。

这么做一开始可能很方便,但存在两个缺点。首先是会导致大量冗余的样式代码。10px 用于文字还是太小了,因此只好在页面各处做补救:段落看着小,改到 1.6rem;侧边栏感觉也小,就再来个 1.6rem;貌似超链接也要 1.6rem……这样一来,代码出错的概率就更大、今后更新样式要改的地方就更多、样式表也会变得更臃肿。

第二,这么做本质上还是像素思维。虽说代码写的是 1.6rem,但脑子里仍然想的是 16px。在响应式网页上,您需要习惯“模糊(fuzzy)”值:1.2em 究竟是多少像素并不重要;重要的是它比继承的字号大那么一点(即 20%);就算不是想要的大小,改改就是了,反复试错,直到满意为止。其实用像素的话也是这么个过程。

使用 em 时很容易陷入具体尺寸的泥沼,纠结于元素计算后的具体像素,尤其像字号这类;为了揪出 em 值的精确大小,您很可能会在无穷无尽的乘法、除法间反复横跳,直到抓狂。与其如此狼狈,不如听我一句劝,首先养成使用 em 的习惯。如果用惯了像素,切换到 em 肯定需要反复练习,但这一切都是值得的。

这并不是说您今后再也不能使用像素了。在和设计师打交道时,适当用一些具体的像素值进行交流也是无可厚非的;在项目初期,也需要确定基本的字号(通常是些标题和脚注的常用字号)。这时用绝对数值来讨论尺寸大小也更通俗易懂。

将大小转换为 rem 值需要做算术题,记得随手备个计算器。给根节点一个字号,也就定义了单位 rem 的大小。自此之后,像素应该仅限于在少数特殊情况下使用,而不能随处可见。

本章还会继续提到像素,这不仅有利于演示相对单位的行为方式,同时也可以帮您习惯 em 的计算。本章过后,将主要使用相对单位来讨论字号。

2.3.1 设置一个合理的默认字号

假设您希望默认字号为 14px,那么就不必先给整个页面一个 10px 的默认字号然后再覆盖掉;直接将根元素的字号设为 14px 即可。期望的值除以继承值(此时为浏览器的默认字号)为 14/16,等于 0.875。在这里使用 em 既调整了默认字号,同时又尊重了用户的字体设置。

将以下代码添加到新样式表的顶部,以便在它基础上设计样式。这样就设置了根节点(<html>)的默认字体。

代码清单 2.9 设置真正的默认字号

:root {  /* 或使用 HTML 选择器 */
  font-size: 0.875em; /* 14/16 (期望的px / 继承的px) = 0.875 */
}

现在页面上已经有了想要的字号,就不必在其他地方画蛇添足了;要改也只改和设计的默认字号不一致的地方,例如标题。

接下来创建一个如图 2.7 所示的面板。需要基于 14px 的字号,利用相对单位来实现。

图 2.7图 2.7 使用相对单位和继承的字体大小创建的示例面板

该面板的 HTML 标记如下。添加到示例页:

代码清单 2.10 面板的 HTML 标记

<div class="panel">
  <h2>Single-origin</h2>
  <div class="panel-body">
    We have built partnerships with small farms around the world to
    hand-select beans at the peak of season. We then carefully roast
    in <a href="/batch-size">small batches</a> to maximize their
    potential.
  </div>
</div>

以下是相应的样式代码:用 em 设置内边距和圆角半径,用 rem 设置标题字号,再用 px 设置边框。更新到您的示例样式表中:

代码清单 2.11 使用相对单位的面板样式

.panel {
  /* 用 em 设置内边距和圆角 */
  padding: 1em;
  border-radius: 0.5em;
  /* 用 1px 添加一个细边框 */
  border: 1px solid #999; 
}
.panel > h2 {
  margin-top: 0;  /* 移除面板顶部的多余空间,后续第3章详述 */
  font-size: 0.8rem;  /* 用 rem 设置标题字号 */
  font-weight: bold;
  text-transform: uppercase;
}

代码清单 2.14 给面板四周添加了一个细边框,并给标题指定了样式。该标题虽然字号偏小、但做了字体加粗和内容全大写处理。(如果设计需要的话,可以改为更大的字号,或者换用其他字体)。

第二个选择器中的 > 是一个 直接后代组合器(direct descendant combinator;它表示选择器中的两元素间存在直接父子关系。此时,该选择器将选中任意做 .panel 元素直接子元素的 h2 元素。(有关选择器和组合器的完整参考资料,参见 附录 A。)

在代码清单 2.10 中,给面板主体添加 panel-body 类只是为了明确含义,在 CSS 中并未用到。因为该元素已经继承了根元素的字号,渲染出来就是期望的效果,无需再变更。

2.3.2 构造响应式面板

更进一步地说,我们甚至可以基于屏幕尺寸,用 媒体查询 来改变根元素的字号。

媒体查询要用到 @media 规则,用于设置仅满足特定屏幕尺寸或媒体类型(例如打印机或屏幕)下的样式。它是响应式设计的核心要素。面板将根据用户屏幕的大小渲染出不同的尺寸(如图 2.8 所示)。

图 2.8 不同屏幕尺寸下的响应式面板图 2.8 不同屏幕尺寸下的响应式面板:300px(左上)、800px(右上)、1440px(底部)

要查看页面效果,按如下代码更新样式:

代码清单 2.12 响应式的基础字号

:root {/* 作用于所有屏幕,但在会被更大屏幕的样式覆盖 */
  font-size: 0.85em;
}
@media (min-width: 800px) {/* 仅适用于 800px 及以上屏幕,并覆盖之前的值 */
  :root {
    font-size: 1em;
  }
}
@media (min-width: 1200px) {/* 仅适用于 1200px 及以上的屏幕,覆盖前面的两个值 */
  :root {
    font-size: 1.15em;
  }
}

上述代码的第一个规则集指定了一个较小的默认字号,这也是我们希望在小屏幕上显示的字号;然后利用媒体查询技术,分别在 800px1200px 及以上 的宽屏上依次逐渐增大字号来覆盖掉默认的字号值。

通过给页面根元素设置不同字号,我们响应式地重新定义了整个页面 emrem 的含义。也就是说,即使不直接修改面板样式,它也是响应式的。在小屏幕上,比如智能手机上,字体会被渲染得更小(13.6px),内边距和圆角半径也相应较小。而在宽度大于 800px1200px 的大屏上,组件字号会相应地分别放大到 16px18.4px。缩放浏览器窗口可以看到这些变化。

如果足够严谨,整个页面的样式都像这样使用相对单位来定义,那么页面就会根据用户浏览器窗口的大小整体缩放。这可以成为设计响应式策略的重要组成部分。靠近样式表顶部的这两个媒体查询,可以极大减少后续 CSS 代码中媒体查询的数量。如果是用像素来定义的,就没那么容易实现了。

同样,如果后来发觉网站上的字体太小或太大,这时仅需改动一行代码就能整体切换字号,进而不费吹灰之力影响整个页面。

2.3.3 缩放单个组件

您还可以通过 em 来单独缩放某个页面组件,比如有时可能需要让同一个组件在页面的某些位置渲染出一个更大的版本。还是用之前的面板来举例说明。首先给面板添加一个 large 类:<div class="panel large">

图 2.9 展示了普通面板和大尺寸面板的区别。效果类似于响应式面板,但这两种尺寸都可以同时在同一页面中渲染出来:

图 2.9 ems 定义的面板可以通过增大字号来放大图 2.9 ems 定义的面板可以通过增大字号来放大

下面对定义面板字号的方法略作修改。还是使用相对单位,只不过要改一下它们的参照对象。首先,在每个面板的父元素中添加声明 font-size: 1rem,这样每个面板无论在页面哪个位置,都有一个可预测的字号。

其次,重新定义标题字号,改成 em 单位制而非 rem,使其相对于新改好的父元素上的 1rem 字号。按代码清单 2.13 更新样式:

代码清单 2.13 创建一个大面板

.panel {
  font-size: 1rem; /* 给组件设置一个可预测的字号 */
  padding: 1em;
  border: 1px solid #999;
  border-radius: 0.5em;
}
.panel > h2 {
  margin-top: 0;
  font-size: 0.8em;  /* 用 em 定义其他字号,使其相对于父元素字号 */
  font-weight: bold;
  text-transform: uppercase;
}

本次修改并不会影响面板的外观,但它可以通过仅新增单个声明来放大面板:用另一个样式值来覆盖父元素上的 1rem 字号即可。由于所有组件的测量值都是基于它的,覆盖后势必影响整个面板的大小。可以通过以下代码定义一个更大的面板:

.panel.large { /* 复合选择器选中同时带 panel 和 large 样式类的元素 */
  font-size: 1.2rem;
}

至此,用 class="panel" 将得到一个普通面板;而用 class="panel large" 则将得到一个更大的面板。同理,可以通过设置较小的字号来缩小面板。如果该面板是一个更复杂的组件,并具有多个字号或内边距,只要其内部样式都是用 em 定义的,就仍然可以仅通过一个声明来独立完成缩放。

您无需完全照搬我演示的内容来操作。emrem 的动态特性是一个强有力的工具,可以结合特定需求进行调整。例如,如果不想让圆角半径同步缩放,将其改成 rem 即可,并在希望同步缩放的属性上使用 em 就行了。花时间熟悉这些相对单位,将使您拥有远比纯像素思维更大且更丰富的选择空间。

CSS:一个生机勃勃的活标准

CSS 由大量 W3C 规范定义而成。最初的 CSS 是一个带版本号的单一规范,但在 2.1 版之后,情况发生了变化。

从那以后,CSS 规范分解为独立的模块,每个模块都有各自独立的版本号。背景和边框的规范脱离了盒模型(box model)模块,以及层叠和继承(cascading and inheritance)模块。这样 W3C 就能够制定 CSS 某个细分领域的新版本,而无需更新其他没发生变化的领域。其中部分规范仍然停留在第 3 版(现称第 3 级,即 level 3);但其他规范已经处于第 4 级或更高级别了,如选择器规范(selectors specification);还有一些规范,如弹性盒子(Flexbox)规范,还处于第 1 级。

也就是说,我们将不再使用某个特定版本的 CSS。它是一个不断发展的活标准(living standard)。每个浏览器都在持续增加对新特性的支持;开发人员也在不断使用这些新特性,并适应这些变化。您可能还会听到“CSS3”这个称谓,但严格来讲,它并不是指某个 CSS 规范的 3.0 版本了,而是指 2010 年代初在短期内发布的一系列规范。

CSS 工作组直到最近才决定支持“CSS4”和“CSS5”的定义。它们不会是规范的具体版本,而是成为一个特性功能的集合(assembly):一个由稳定的、业已构成该语言基本组成部分的特性功能(CSS4)、与目前采用率正稳步攀升的新功能特性(CSS5)的集合。本书不会使用这些称谓,因为它们尚未完全定义;但我会介绍这两个类别的功能,甚至一些最终有望被视为部分 CSS6 的全新功能。

emrem 是最常用的相对单位,但它们并不是唯一可用的相对单位类型。在了解了它们提供的灵活性后,下面再来看看另一种重要的相对单位。

(本小节完)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/771662.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

安卓常用的控件

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 在Android开发中&#xff0c;控件&#xff08;也称为视图或控件组件&#xff09;是构建用户界面的基本元素。它们…

设计模式-代理模式和装饰者模式

二者都是结构型的设计模式. 1.代理模式 1.1定义 为其他对象提供一种代理以控制对这个对象的访问. 代理从code实现方面分为静态代理和动态代理两种&#xff1b; 从适用范围来看,分为远程代理,虚拟代理,保护代理,智能引用几种. 远程代理:为某个对象在不同的内存地址空间提供…

Esxi硬件日志告警

原创作者&#xff1a;运维工程师 谢晋 Esxi硬件日志告警 故障描述故障处理 故障描述 主机报错硬件对象状态告警 在Esxi监控硬件内发现Systemctl Manager Module 1 Event log 0报警&#xff0c;该报警是Esxi事件日志保存空间满了&#xff0c;需要清理空间。 故障处理 开启…

实现第一个神经网络

PyTorch 包含创建和实现神经网络的特殊功能。在本节实验中&#xff0c;将创建一个简单的神经网络&#xff0c;其中一个隐藏层开发一个输出单元。 通过以下步骤使用 PyTorch 实现第一个神经网络。 第1步 首先&#xff0c;需要使用以下命令导入 PyTorch 库。 In [1]: import…

Android super.img结构及解包和重新组包

Android super.img结构及解包和重新组包 从Android10版本开始&#xff0c;Android系统使用动态分区&#xff0c;system、vendor、 odm等都包含在super.img里面&#xff0c;编译后的最终镜像不再有这些单独的 image&#xff0c;取而代之的是一个总的 super.img. 1. 基础知识 …

字节一年,人间三年

想来字节做研发&#xff0c;可以先看我这三年的体会和建议。 大家好&#xff0c;我是白露啊。 今天和大家分享一个真实的故事&#xff0c;是关于字节网友分享自己三年的工作经历和感受。 由于白露也曾在字节待过两年&#xff0c;可以说&#xff0c;说的都对。 你有没有想过来…

51-5 权限维持2 - 影子账号(隐藏用户)

权限维持技术 权限维持技术(Persistence,也称为权限持久化)是一种能够在系统重启、用户更改密码或其他可能导致访问中断的情况下保持对系统访问的技术。例如,它包括创建系统服务、利用计划任务、修改系统启动项或注册表、以及映像劫持等方法。 创建影子账户 影子账户是指隐…

目标检测入门:3.目标检测损失函数(IOU、GIOU、GIOU)

目录 一、IOU 二、GIOU 三、DIOU 四、DIOU_Loss实战 在前面两章里面训练模型时&#xff0c;损失函数都是选择L1Loss&#xff08;平均绝对值误差&#xff08;MAE&#xff09;&#xff09;损失函数&#xff0c;L1Loss损失函数公式如下: 由公式可知&#xff0c;L1Loss损失函数…

Midway Serverless 发布 2

可以看看优化后的开发情况&#xff0c;不仅和应用一样&#xff0c;速度还比较快&#xff0c;也不会生成临时目录&#xff0c;修改实时生效。 这是 v2.0 和 v1.0 的根本性变化&#xff0c;也是整体架构升级带来的巨大优势。 当然&#xff0c;这一块并不是功能的新增&#xff0c…

【C++】类和对象(中)--上篇

个人主页~ 类和对象上 类和对象 一、类的六个默认成员函数二、构造函数1、构造函数基本概念2、构造函数的特性 三、析构函数1、析构函数的概念2、特性 四、拷贝构造函数1、拷贝构造函数的概念2、特征 一、类的六个默认成员函数 如果有个类中什么成员都没有&#xff0c;那么被称…

Python从0到100(三十六):字符和字符集基础知识及其在Python中的应用

1. 字符和字符集概述 字符(Character)是构成书面语言的基本元素&#xff0c;它包括但不限于各国家的文字、标点符号、图形符号和数字。字符集(Character set)则是一个包含多个字符的系统&#xff0c;用于统一管理和编码不同的字符。 常见字符集 ASCII&#xff1a;最早的字符…

Truenas scale入坑

家里有一台刚上大学时配的电脑&#xff0c;看着无用武之地&#xff0c;又还能用&#xff0c;于是想那它来搞个私有云nas。 一、选择想要入的坑 一开始对这块没什么了解和概念&#xff0c;最早是在旧主机上安装了个Ubuntu&#xff0c;然后再安装CassOS小尝试了下。可能CassOS里…

【Apache Doris】周FAQ集锦:第 9 期

【Apache Doris】周FAQ集锦&#xff1a;第 9 期 SQL问题数据操作问题运维常见问题其它问题关于社区 欢迎查阅本周的 Apache Doris 社区 FAQ 栏目&#xff01; 在这个栏目中&#xff0c;每周将筛选社区反馈的热门问题和话题&#xff0c;重点回答并进行深入探讨。旨在为广大用户和…

eNSP-VLAN虚拟局域网

一、出现Vlan的原因 同一个局域网&#xff0c;使用交换机连接&#xff0c;虽然比集线器相连&#xff0c;降低了广播风暴&#xff0c;但是局域网主机数量够多的时候&#xff0c;正常的广播数据(arp、dhcp)也很影响网络性能&#xff0c;所以还需要进一步降低广播风暴——VLAN (图…

双指针算法:快速排序模拟实现

目录 1.思路解析 2&#xff1a;代码展示 1.思路解析 使用双指针pre和cur 指针cur用于检测符合条件的数据 cur和pre数据发生交换用于将符合条件的数据&#xff08;比key小&#xff09;向左扔 一轮循环结束时&#xff0c;以pre为分界点&#xff0c;除去key&#xff0c;pre左边的…

SpringMVC 的工作流程和详细解释

Spring MVC&#xff08;Model-View-Controller&#xff09;框架是基于经典的 MVC 设计模式构建的&#xff0c;用于开发 Web 应用程序。下面是 Spring Boot MVC 的工作流程和详细解释&#xff1a; 1.客户端发起请求 1.客户端&#xff08;通常是浏览器&#xff09;发起 HTTP 请求…

VUE Pinia状态持久化

效果 实现方法 插件&#xff1a;pinia-plugin-persistedstate 链接地址 具体操作 安装 npm i pinia-plugin-persistedstate 添加到 pinia 实例上 import { createPinia } from pinia import piniaPluginPersistedstate from pinia-plugin-persistedstateconst pinia cre…

自动化设备上位机设计 一

目录 一 设计原型 二 后台代码 一 设计原型 二 后台代码 namespace 自动化上位机设计 {public partial class Form1 : Form{public Form1(){InitializeComponent();}private void Form1_Load(object sender, EventArgs e){}} }namespace 自动化上位机设计 {partial class Fo…

PDM与ERP物料编码技术在产品设计中的区别与应用

01 概 述 产品是企业赖以生存的基础&#xff0c;产品数据是企业最基本的也是最重要的数据&#xff0c;产品数据存在于产品设计、采购、生产、销售、服务、库存管理等全过程中。通过对产品设计数据进行编码&#xff0c;并增加采购、库存、生产、制造等属性信息&#xff0c;可以…

2.5 C#视觉程序开发实例1----设计一个IO_Manager

2.5 C#视觉程序开发实例1----设计一个IO_Manager 第一步目标&#xff1a; 1 实现获取IO触发信号Trig0 2 能够实现程序切换 3 图像处理后能够输出一个脉冲 1 IO 引脚定义 1.1 输入信号定义 1.2 输出信号定义 2 IO时序图 2.1 触发时序 2.2 切换程序时序图 3 IO_Manager.cs …