用rem单位构建灵活的响应式布局:一个实例解析

411 阅读6分钟

摘要

本文通过分析一段具体的HTML代码,探讨了如何利用rem单位创建响应式设计,并解决实际开发中遇到的一些问题。我们将详细讲解这段代码的工作原理、rem单位的作用、以及JavaScript动态调整根元素字体大小的方法。

HTML结构与初始化设置

<!DOCTYPE html>
<html lang="en" style="font-size: 75px;">

在文档开始处,我们设置了HTML标签的初始字体大小为75px。这个值是临时的,因为稍后我们会使用JavaScript来动态调整它。这样做是为了确保在脚本加载和执行之前,页面有一个明确的基础字体大小。

动态设置根字体大小的JavaScript逻辑

<script>
    (function () {
        function calc() {
            const w = document.documentElement.clientWidth;
            document.documentElement.style.fontSize = w / 10 + 'px';
        }
        calc();
        window.onresize = function () {
            calc();
        }
    })();
</script>

此段代码是一个立即执行函数表达式(IIFE),用于计算并设置根元素(即<html>)的字体大小。它根据视口宽度(clientWidth)来确定新的字体大小,公式为 w / 10 + 'px',这意味着如果屏幕宽度为320px,则根字体大小将被设置为32px。每当窗口尺寸改变时(例如平板的横屏竖屏),都会重新调用calc函数以更新字体大小,从而保证了页面元素能够随屏幕大小自适应缩放。

在这段代码中,document 是一个内置的全局对象,它表示当前加载的网页文档。document 对象是浏览器提供的 DOM(文档对象模型) API 的一部分,允许 JavaScript 与 HTML 页面进行交互。具体来说,document 提供了访问页面结构、样式和内容的方法和属性。

  • document.documentElement:这是对HTML文档根元素 (<html>) 的引用。每个HTML文档都有一个根节点,即 <html> 标签,它是所有其他元素的父级或祖先节点。通过 document.documentElement,我们可以直接操作这个根元素,比如设置它的样式属性。
  • clientWidth:这是一个只读属性,返回元素的内容区宽度(以像素为单位),包括内边距(padding),但不包括滚动条、边框(border)、外边距(margin)。在这个例子中,document.documentElement.clientWidth 返回的是整个视口(viewport)的宽度,也就是用户当前可视区域的宽度。
  • style.fontSize:这用于获取或设置指定元素的CSS font-size 属性。在本例中,我们使用它来动态调整 <html> 元素的字体大小,从而影响到所有使用 rem 单位定义尺寸的子元素。
window.onresize = function () {
    calc();
};

window.onresize = function () { calc(); }; 是一段用于监听窗口大小变化的JavaScript代码。它为 window 对象的 onresize 事件指定了一个处理函数,每当浏览器窗口的尺寸发生变化时(例如用户调整了浏览器窗口的大小),这个处理函数就会被调用。

window 对象

  • 全局对象window 是浏览器环境中的全局对象,表示浏览器窗口或标签页。所有的全局变量和函数都是 window 的属性。
  • 事件处理window 提供了一系列事件处理程序属性,允许开发者响应用户的交互行为或其他系统事件。

onresize 事件

  • 定义onresize 是 window 对象的一个事件处理程序属性,当窗口大小改变时触发。
  • 用途:通常用于执行那些依赖于窗口尺寸的操作,比如调整布局、重新计算某些元素的位置或大小等。

function () { calc(); }

  • 匿名函数:这里定义了一个匿名函数作为 onresize 事件的处理程序。每当 onresize 事件发生时,这个匿名函数就会被执行。
  • 调用 calc() 函数:在匿名函数内部,我们调用了之前定义的 calc() 函数。这个函数负责根据新的窗口宽度重新计算并设置根元素 (<html>) 的字体大小。

使用rem单位定义样式

<div style="width: 10rem; height: 2rem; background-color: red;"></div>

这里我们使用了rem单位来指定宽度和高度。由于根元素的字体大小是动态变化的,因此这些元素的实际尺寸也会随着屏幕宽度的变化而自动调整,实现了良好的响应性。

解决inline-block元素对齐问题

<div style="font-size: 0;">
    <div style="width: 5rem; height: 2rem; background-color: green; display: inline-block; font-size: 20px; color: white">
        111</div>
    <div style="width: 5rem; height: 2rem; background-color: blue; display: inline-block;">222</div>
</div>

image.png

<div style="font-size: 0;"> 的作用解释:

在这个例子中,外部的<div>容器设置了font-size: 0;。这种做法的主要目的是为了消除inline-block元素之间的空白间距。默认情况下,inline-block元素之间会存在一些由HTML中的换行符或空格引起的间隙,这可能会导致布局上的不精确。通过将父级容器的字体大小设置为0,可以有效地移除这些不必要的间距。如果不加style="font-size: 0;" 那么必须删除中间两个div之间的空格,否则两个div不会出现在同一行。

此外,当子元素中有文本内容时(如绿色盒子中的“111”),即使父级容器的字体大小为0,子元素仍然可以通过它们自己的font-size属性来显示正常大小的文字。这种方式不会影响到文本的可读性,但确实解决了因inline-block元素间空白引起的问题。

这里我们使用了rem单位来指定宽度和高度。由于根元素的字体大小是动态变化的,因此这些元素的实际尺寸也会随着屏幕宽度的变化而自动调整,实现了良好的响应性。

为什么蓝色盒子下降了?

这是因为两个inline-block元素默认按照基线(baseline)对齐,而绿色盒子中包含的文本“111”会占用一定的空间,使得绿色盒子的基线低于其底部边缘。因此,当两个盒子按基线对齐时,蓝色盒子看起来像是下降了,实际上它是根据绿色盒子的内容基线来调整自己的位置。

解决方案

如果你希望两个盒子顶部对齐,可以在它们的样式中添加vertical-align: top;

<div style="width: 5rem; height: 2rem; background-color: green; display: inline-block; font-size: 20px; color: white; vertical-align: top;">111</div>
<div style="width: 5rem; height: 2rem; background-color: blue; display: inline-block; vertical-align: top;">222</div>

这样,两个盒子都会按照它们各自的顶部边缘对齐,从而解决蓝色盒子下降的问题。

image.png

总结

通过上述代码片段,我们可以看到rem单位在创建响应式布局中的强大作用。它不仅使得页面元素更加灵活,而且还能提高用户体验,特别是在不同设备上浏览网页时。同时,我们也学习到了如何处理一些常见的布局问题,比如inline-block元素的对齐问题。这种方法非常适合企业级应用,因为它提供了更好的可维护性和跨设备的一致性。