最好用的网站建设软件,wordpress linux安装,域名备案查询系统,征婚网站咋做一个挑战
假设您需要创建一个两列布局。是的#xff0c;最简单的那种#xff1a;左边一列#xff0c;右边一列#xff0c;中间有一些空隙。有一个明显的现代解决方案#xff1a;
.columns {display: grid;grid-template-columns: 1fr 1fr;gap: 20px;
}完毕#xff01;当…一个挑战
假设您需要创建一个两列布局。是的最简单的那种左边一列右边一列中间有一些空隙。有一个明显的现代解决方案
.columns {display: grid;grid-template-columns: 1fr 1fr;gap: 20px;
}完毕当然可以但是如果我们需要支持一些较旧的浏览器怎么办然后是 Flexbox。好的那么文本从一栏流到另一栏呢没问题多列。旧的电子邮件客户端怎么样好吧我们中的一些人仍然记得如何使用表格布局。
你看这就是 CSS 的美妙之处几乎每个问题都有多种解决方案因此您可以选择适合您的确切需求的解决方案。但不仅仅是 CSS还有许多 HTML 和 SVG 技巧在某些情况下可以为您提供帮助。它就像一种自然语言你的词汇量越大你就越能表达自己。
甚至还有一个基于此的面试策略你可以要求人才想出多种方法来解决同一个简单的任务。而这正是本文的想法来源。
我的一个朋友曾经用求职面试的任务来挑战我你知道多少种制作双栏布局的方法多么愚蠢的问题对吧但这让我比我想象的更深入。有一阵子我什么也想不起来直到我在脑海中仔细考虑了所有可能和不可能的想法。它归结为 11 种制作带有间隙的两列的方法。
但我更愿意称他们为 65将他们分为两组 六个非常合理的它们有意义并且可以用于实际的生产项目或用于。 五个完全错误的有一些怪癖看起来或行为很奇怪但仍然完成了任务。
顺便说一句在所有现代浏览器中结果看起来都一样即使是五个奇怪的浏览器。
设置和规则
为了让它更接近现实我决定将整个事情分成两个部分
列固定布局有两列和一个间隙。
新闻适合专栏的流动卡片。
这个想法是有一个可以填充真实内容的列组件而不仅仅是绘制两个彼此相邻的彩色框。 新闻组件将始终保持不变我们将只使用栏目组件。第一个新闻将有一个浅绿色的背景第二个 - 著名的桃花心。
合理六
您将如何对合理选项列表进行排序好吧可能不是按字母顺序排列的。从最好到最坏他们都擅长某些情况并具有一些独特的优势。所以我决定按照历史的顺序我先从我学过的开始到现代的结束。
table
演示两列和一个表格间隙
表格是浏览器中第一个可用的布局工具。早在 2002 年我就用它们创建了我的第一个网页。要制作表格布局您需要一个父包装器 table、一些 tr 行和用于列的 td 单元格。
table classcolumns
trtd classcolumns__item columns__item--first!-- Left --/tdtd classcolumns__item columns__item--second!-- Right --/td
/tr
/table我将对类名使用 BEM 表示法就像我在真实项目中所做的那样。我们将为所有演示使用几乎相同的列组件结构但在某些情况下我们不需要第一/第二修饰符。
值得注意的是尽管表格被列在“合理”组中但它们已经过时了应该只用于……你知道的表格和表格数据。您可能有理由将它们用于电子邮件布局但我什至不确定是否还需要它们。从可访问性的角度来看这是一场噩梦所以让我们把它当作一堂历史课。
为了使表格消失并表现得像一个中性列组件我们需要修复一些东西border-collapse 和 padding 属性以删除额外的填充和 vertical-align: top 以将内容对齐到顶部。是的表格曾经是垂直对齐事物的最简单方法。
.columns {border-collapse: collapse;
}.columns__item {padding: 0;width: 50%;vertical-align: top;
}为了在 2002 年留下一个空白我会在中间使用另一个空单元格和一些额外的元素来固定宽度。疯狂的时代但今天我更喜欢一些填充左边 10px右边 10px不要太花哨。
.columns__item--first {padding-right: 10px;
}.columns__item--second {padding-left: 10px;
}您可能认为在 div 上使用 display: table 可以被视为制作两列布局的另一种方式。但我认为表格就是表格这种行为是来自浏览器还是作者风格并不重要。
news来了
article classnewsh2 classnews__titleTitle/h2p classnews__leadContent/p
/article一旦我们在每个表格单元格中都有两个新闻第一个“合理”的布局就准备好了。还有十个去
Floats
演示两列和一个带浮动的间隙
我学到的下一个布局技术是浮动。它们是为类似报纸或杂志的内容布局而发明的在这些布局中文本会“漂浮”在图片、引语或类似元素周围。我首先在 Adobe PageMaker 中尝试了这一点当时我正在布置一份实际的报纸而且在 Web 上也可以使用浮动效果非常好。
一些聪明的人意识到如果你去掉文本将一个框向左浮动另一个向右浮动这样就形成了一个布局尽管确保浮动元素不会争夺空间很重要否则它们会开始从行中掉落。
在这种情况下我们不需要任何特殊的 HTML 元素来使其工作所以让我们坚持使用抽象 div。毕竟这只是一个布局。
div classcolumnsdiv classcolumns__item columns__item--first!-- Left --/divdiv classcolumns__item columns__item--second!-- Right --/div
/div这是浮动的主要问题它们需要被“清除”。如果您的容器中有浮动元素它们会掉出容器并且容器会折叠到零高度。
清除浮点数主要有两种方式
更改容器的某些属性。
在容器的末尾放置一些虚假内容。
让我们选择第一个选项。回到浮动布局时代我们会使用 overflow: hidden它有一个明显的缺点内容被剪裁。但是今天我们可以使用一个特殊的显示值
.columns {display: flow-root;
}我会称它为 display: clear-floats但这就是我没有机会进入 CSSWG 的原因。
现在我们需要设置列的宽度因为它们不像表格单元格那样粘在一起所以可以将它们分开宽度的一半减去间隙的一半。那时候 calc 的魔力还没有就像 border-radius 一样但现在是 2022 年所以
.columns__item {width: calc(50% - 10px);
}最后让我们将它们浮动到父对象的不同侧面
.columns__item--first {float: left;
}.columns__item--second {float: right;
}你有它第二个稍微“合理”的双列选项。让我们试试下一个
02、内联块
演示两列和一个内联块的间隙
基于内联块的布局大约与浮动同时流行。但他们对付起来有点挑剔。我们将使用与浮动相同的标记但我们不需要任何第一/第二修饰符。
首先我们需要从我们的列中创建内联块以使整个事情正常进行。因为它们是内联的所以很乐意保持“内联”但它们也是块您仍然可以设置它们的宽度与内联元素不同。让我们也将它们对齐到顶部而不是默认基线。
.columns__item {display: inline-block;width: calc(50% - 10px);vertical-align: top;
}现在我们的news块在“栏目”中但它们之间的差距看起来不对。它看起来像一个典型的白色空间。
好吧因为它是我们 HTML 中的所有嵌套都被浏览器例行压缩到一个空白区域因为它是一个内联上下文。
有两种流行的方法可以摆脱它 将父项的字体大小设置为零。 删除标记中标签之间的所有空格。
第二种方式相当脆弱所以让我们使用第一种方式。由于 font-size 是一个继承属性我们不要忘记为内容恢复它。
.columns {font-size: 0;
}.columns__item {font-size: 16px;
}一旦我们的两个列都紧挨着放置我们就可以在它们之间精确地留出 20px 的间距。由于它是内联上下文我们可以将我们的父元素视为一个句子这使得嵌套列成为单词……你看到它的去向了吗那就对了word-spacing 属性可以解决问题。
.columns {word-spacing: 20px;font-size: 0;
}.columns__item {word-spacing: normal;font-size: 16px;
}我们不要忘记将嵌套元素重置为正常就像我们对字体大小所做的那样。
那是第三种方式接下来的三种方式终于开始有意义了我保证。
03、多列
演示两列和多列的间隙
现在是第一个为布局设计的布局技术的时候了。嗯差不多。多列可以获取任何内容并使其在列之间流动并在其间留有一些原生间隙。正如在报纸上看到的那样
.columns {columns: 2 20px;
}而已我不是像 flex 这样神奇的速记属性的忠实粉丝但我就是无法抗拒。在一个属性中设置了两列和一个 20 像素的间距是不是很优雅但是有一点不对劲
由于内容从一栏流向另一栏因此一些块部分也在流动。它看起来像一个破损的门户或一台旧电视但有一个简单的解决办法礼貌地避免对残酷的闯入财产的价值。
.columns__item {break-inside: avoid;
}那很快第四种双列布局。让我们看看是否有比这更好的东西。
04、弹性盒
演示两列和一个 Flexbox 间隙
现在最流行的布局技术来了。它已经存在了一段时间但在过去浏览器实现存在差异并且只是明显的错误使得 Flexbox 难以使用。但现在不是了
现在很简单
.columns {display: flex;gap: 20px;
}.columns__item {width: 50%;
}但是如果您不能只支持最近的浏览器版本那么您将不得不告别 gap 属性并使用一些额外的代码在列之间留出一些空间。将列推到两侧并确保它们的宽度像我们之前所做的那样使用 calc 设置。
.columns {display: flex;justify-content: space-between;
}.columns__item {width: calc(50% - 10px);
}最后一些现代且可用的东西已经是第五个了与我们讨论过的许多技术不同Flexbox 在今天很重要。但这些天我经常寻求下一个选择。
05、网格布局
演示两列和网格布局的间隙
说真的网格布局在几乎所有布局情况下都非常有意义即使对于像在单词旁边放置一个图标这样的微布局也是如此。记住这就是我们的出发点
.columns {display: grid;grid-template-columns: 1fr 1fr;gap: 20px;
}它的美妙之处在于整个布局由容器定义。当然在某些情况下您需要将一些属性应用于嵌套元素但可以仅使用容器的属性来实现基本布局。它对于使您的布局响应媒体查询特别有用。
此外由于 grid-gap 和后来的 gap 属性是初始网格布局实现的一部分与 Flexbox 中的 gap 相比您不必担心浏览器兼容性。
制作两列布局的第六种方法太简单了。别担心我们会遇到一些非常奇怪的事情。
怪五
这里没有历史顺序。我只是试图列出从最不奇怪到完全错误的选项。又是什么问题让我把这些方法分成了一个特殊的组
首先他们并不总是能很好地处理内容流。在 Web 上我们使用的原则是下一个内容块将紧跟在前一个内容块之后而不是在它上面。一旦前一个块变小或变大所有后续块都会随之上下移动。
如果您曾经手动编写过 SVG 文件您可能知道我在说什么。想象一下如果每个块都绝对定位在文档的左上角。那将使我们的工作更加困难。对于 SVG 作为图像格式来说完全没问题但对于内容布局来说是不可接受的。
其他方法使用额外的标记使事情变得过于复杂滥用某些 CSS 属性使其只能在单个浏览器中工作或者损害内容的可访问性。不过让我们一一探索它们以学习新知识或者至少获得一些乐趣。
定位 演示两列和一个带定位的间隙
定位不是最好的布局技术因为它破坏了内容流而内容流是 Web 的主要原则之一。但在某些情况下它仍然是一个有用的工具。与 SVG 中的形状不同我们不必每次都从文档的左上角定位元素幸运的是有一种嵌套定位的方法。
让我们通过 position: relative 将父组件保持在流程中。在这种情况下嵌套列定位将从父组件开始即使它会像浮动一样折叠到零高度。不幸的是没有办法“清除”定位元素。
.columns {position: relative;
}.columns__item {position: absolute;top: 0;width: calc(50% - 10px);
}由于绝对定位元素处于它们的平行世界中它们往往以一种有趣的方式包含事物所以让我们用 calc 来限制它们的宽度。就像浮动一样让我们将列推到两侧这样它们就不会重叠。
.columns__item--first {left: 0;
}.columns__item--second {right: 0;
}嗯这个演示有些不同与之前的紫色演示不同这个演示的页面背景充满了番茄色。那是因为突出这个群体的性质看起来稍微危险一些。
所以你有它第一个奇怪的方式。没什么可怕的对吧当然我们只是在热身。
书写方式 演示两列和一个带有书写模式的间隙
要了解下一个方法的工作原理让我们考虑一下这段文字不是它的含义而是它的形状。我是用水平线写的从上到下一条接一条。这种行为在许多语言中都很常见并由 writing-mode 属性控制。在本例中它的值为 horizontal-tb意思是“水平从上到下”。
但在某些语言中文本可以垂直列显示而不是水平行。这为我们提供了另外两个书写模式值vertical-rl 和 vertical-lr。值的第一部分相当简单第二部分取决于文本的方向LTR 或 RTL。无论如何在这种垂直模式下新行从前一行向左或向右移动。
知道了让我们尝试一个愚蠢的事情将父块的书写模式更改为垂直这样行就会变成列并从右边开始。
.columns {writing-mode: vertical-lr;
}看这已经看起来像一个布局了但有些事情需要修复才能使其可用。就像在 font-size: 0 的情况下我们需要将列的 writing-mode 恢复到以前的状态。当我们这样做的时候让我们为我们的列添加宽度。
.columns__item {width: 390px;writing-mode: horizontal-tb;
}不幸的是我们无法在 Flexbox 或 Grid 布局之外使用 gap 属性。因此让我们使用古老的技巧一列后跟另一列将获得正确的边距。
.columns__item .columns__item {margin-left: 20px;
}我可能应该改用 .columns__item——第一个选择器但这太容易了。我在这里尝试使用尽可能多的技巧
希望你能在 font-size: 0 和 writing-mode: vertical-lr 情况下闻到同样奇怪的东西它们既脆弱又滥用了不适合布局的属性。
仍然是第二个奇怪的双列布局。准备好再来一个了吗我们走吧
SVG
演示两列和一个 SVG 间隙
我已经提到 SVG 只是一种可以手动编码的图形格式但不符合我们的布局需求。对不起我骗了你。你一开始没有准备好接受真相。但是现在你已经经历了很多奇怪的事情并且准备好迎接任何事情。
让我们从 CSS 开始……然后马上结束。这是我们唯一需要的样式。
.columns {display: block;width: 100%;height: 100%;
}你已经可以看到这种方式对内容流的友好程度不亚于绝对定位一点也不。至于 HTML它看起来不会很漂亮
svg classcolumnsforeignObjectarticle classnews news--firsth2 classnews__titleTitle/h2p classnews__leadContent/p/article/foreignObjectforeignObjectarticle classnews news--secondh2 classnews__titleTitle/h2p classnews__leadContent/p/article/foreignObject
/svg好吧它不完全是 HTML而是带有一些 HTML 的 SVG。尽管如此在 HTML 文档中。我不知道它是否合法但它是完全有效的
文件检查完成。没有错误或警告显示。
通常除了类似命名的 a 和 script SVG 元素外SVG 不允许您在其中包含一些任意的 HTML。但是如果您使用 foreignObject 很好地询问那就没问题了。
为了让它工作我们需要定位这些外部代理……抱歉我的意思是使用表示属性的外部对象。这在 SVG 中很常见也很方便因为它只是一种图形格式还记得吗我们有 x/y 而不是左/上其余的非常相似。
但是没有简单的方法来制作 right: 0 替代品所以我们也必须从左边定位右边的列。
foreignObject x0 y0 width390 height100%!-- Left --
/foreignObject
foreignObject x410 y0 width390 height100%!-- Right --
/foreignObject不幸的是SVG 包装的内容无法像 HTML 元素那样影响父元素的尺寸。所以我们必须自己设置它在我们的例子中它占据了整个页面的高度。
这是第三个奇怪的双列布局。让我们探索一个稍微合理的第四个以防万一。
元素
演示两列和一个带元素的间隙
在设置规则时我提到我们正在尝试在这里做一些实用的事情而不仅仅是把两个盒子画在一起。但是有一种方法可以获取一些真实的内容并将其绘制为背景图像。它不是 Canvas它只适用于 Firefox你不应该使用它。听起来很令人兴奋
为了让它工作让我们将列的大小调整为父宽度的一半减去间隙的一半这是通常的做法。然后我们剪辑它们使它们变得不可见并通过定位将它们从流中移除。当然为什么不呢。
.columns__item {position: absolute;clip-path: inset(50%);width: calc(50% - 10px);
} 看柱子还在那里但它们是看不见的。让我们把它们放回我们需要的地方但是父级的高度现在折叠起来没有任何内容让我们用 height: 100% 来修复它。相对定位将保持这些列相对于父块的大小和位置。
.columns {position: relative;height: 100%;
}
现在是施展魔法的时候了。仅对于此演示我们在标记中为每个新闻设置了 IDnews-first 和 news-second。我们可以使用这些 ID 使这些元素成为具有 -moz-element 函数的 background-image 属性的来源。多亏了多个背景图片我们可以只使用一个元素。定位我们的元素第一个到左上角第二个到右上角。我们不需要重复。
.columns {background-image:-moz-element(#news-first),-moz-element(#news-second);background-position:left top,right top;background-repeat: no-repeat;
}VS Code 的 CSS 语法认为函数中的 ID 有问题但它有效好吧目前仅在 Firefox 中。正如我之前提到的它还没有准备好用于任何生产代码。虽然它不只是编造的因为它是 CSS Images Module Level 4 草案的一部分。
我们希望在某个时候所有浏览器都支持此功能。它只在 Firefox 中存在了一段时间。但是再一次强调用它来布置内容在任何情况下都不是一个好主意。
第四种奇怪的布局方法与接下来的方法相比并没有那么糟糕。我真诚地提前道歉。
Frames
演示两列和一个带框架的间隙
演示地址https://pepelsbey.dev/articles/two-columns/demos/frame.html
您可能知道 iframe 是什么但您可能并没有经常使用 frame 元素。它通过为您提供另一个文档的“窗口”来达到类似的目的。它们之间的主要区别是 iframe 是一个独立的元素而 frame 元素以称为 frameset 的集合出现。这些框架集具有一些布局功能
为了制作我们的目标布局我们需要一组中的三个框架两个用于列一个在中间用于间隙。我们框架的确切宽度可以在 cols 属性中指定。总宽度超过 100% 并不重要浏览器不会溢出集合就像处理表格一样。
frameset cols50%, 20, 50% border0frame frameborder0 srcframe frameborder0 srcframe frameborder0 src
frameset与“i”代表“内联”的 iframe 元素不同frameset 应该占据整个窗口。不仅如此它还应该取代 body 元素。在包含其他元素的页面上使用这种布局技术是不可能的。没问题我们可以将它包装在另一个内联框架中。
框架还需要外部文档才能工作因此您必须将 frameset 分离到 columns.html 中并通过 src 属性将其链接到 iframe 中。您还需要将news分成 news-one.html 和 news-two.html 文件并通过 src 属性链接它们。请记住我提前为该方法道歉
但是还有另一种方法可以让它在没有外部文件和嵌套文档的情况下工作。好吧有点。我们可以使用 data:uri 并将所有内容嵌套在一个文档中。但是我们应该小心引号你会明白为什么的。
让我们从 iframe 的 CSS 开始没什么特别的
.columns {display: block;width: 100%;height: 100%;border: none;
}标记来了这是最令人兴奋的部分。我们在 src 属性中没有文件的 URL而是用特殊的 data:text/html 前缀让浏览器知道它不是 URL而是“文件”本身。
内容以 !DOCTYPE html 开头以保持标准模式然后跟随字符集以防万一。我跳过了 title 元素因为我是个坏人。请永远不要这样做。
iframe classcolumns srcdata:text/html,!DOCTYPE htmlmeta charsetutf-8frameset cols50%,20,50% border0frame frameborder0 srcdata:text/html,frame frameborder0 srcdata:text/html,frame frameborder0 srcdata:text/html,/frameset
/iframe现在我们在 src 属性中有三个带有空文件的嵌套框架。我们要让中间的那个空着因为它只是一个缺口。至于另外两个会有我们的新闻文件。我通常在我的标记中使用双引号但我必须在嵌套文档中切换为单引号才能使其正常工作。在下一个嵌套级别我将完全停止使用它们。
因此让我们像处理 frameset 一样获取实际内容准系统 HTML 文档、一些样式和新闻。不幸的是我无法让 link relstylesheet hrefnews.css 工作所以我不得不使用内联样式。但我不会因为在如此混乱的标记中放弃而责怪它。
iframe classcolumns srcdata:text/html,!DOCTYPE htmlmeta charsetutf-8frameset cols50%, 20, 50% border0frame frameborder0 srcdata:text/html,!DOCTYPE htmlmeta charsetutf-8style/* News styles *//stylearticle classnewsh2 classnews__titleTitle/h2p classnews__leadContent/p/article/frameset
/iframe第二条news也是如此唯一不同的是背景颜色和内容。最让我吃惊的是它可以在 Firefox、Chrome 和 Safari 中运行尽管 frameset 和 frame 元素已经被弃用了很长时间。
我唯一无法解决的问题是 Safari 中的 frameset 背景颜色由于某种原因它是白色的尽管它在其他浏览器中是透明的。这种行为在任何地方都没有提及即使在出于兼容性原因详细描述 frame 和 frameset 行为的 HTML 规范中也是如此。
那是我想出的最后一个奇怪的双列技术。实用吗一定不行我建造它有很多乐趣吗确实。