不到一年前,Trent Walton 发布了 内容编排,其中他哀叹了响应式布局的一些困难和局限性。
有时,当内容重新流向时,似乎所有的网站架构和规划都将付诸东流。
你必须承认,相当多的响应式设计最终会变成
- 将所有内容挤入一列
- 将侧边栏推到底部
*咳嗽* 这个网站就是这样 *咳嗽*
Trent 提到,可能更合适的做法是将内容“交错排列”。

也就是说,将内容片段以更周到或更有用的方式折叠在一起,形成单列。
实际示例:广告折叠
考虑在大型浏览器窗口大小下的布局。 两列。 文章位于左侧的宽列中,广告位于右侧的窄列中。
在较窄的浏览器窗口大小下,我们决定降至单列。 此布局可能是使用浮动完成的,浮动至今仍然是最常见的布局方法。 不幸的是,这可能意味着将两列都设置为 100% 宽,并让它们的源顺序决定哪一个在上面。 意思是:将所有广告推到底部。 这可能不太理想。 更妙的做法可能是将广告折叠到内容中。
但是怎样做呢?
可能有很多方法可以做到这一点。 使用 JavaScript,您可以测量窗口宽度并在 DOM 中重新排列内容。 这对我来说似乎很繁重,但浏览器的支持会很好。 我更倾向于依靠 CSS 来做这种事情。 这正是 CSS 的(应该)用处。 网格布局 可能为我们提供了一些可能性,但对于本教程,让我们使用最新的 CSS 区域,这是 Adobe 的贡献。
HTML
<section class="main-content">
<article> ... </article>
<div class="ad-region-1">
<!-- empty, ads flow into here as needed -->
</div>
<article> ... </article>
<div class="ad-region-2">
<!-- empty, ads flow into here as needed -->
</div>
<article> ... </article>
<div class="ad-region-3">
<!-- empty, ads flow into here as needed -->
</div>
</section>
<aside>
<!-- Fallback content in this flow region, probably clone #ad-source -->
</aside>
<!-- Source of flowing content, essentially hidden as an element -->
<div id="ad-source">
<a href="#"><img src="ads/1.jpg"></a>
<a href="#"><img src="ads/2.jpg"></a>
<a href="#"><img src="ads/3.jpg"></a>
<a href="#"><img src="ads/4.png"></a>
</div>
请注意,"内容"(我们的广告)位于页面底部的 <div>
中。 一旦我们设置了 CSS 区域,该元素将基本上被隐藏,其中的内容将流入我们告诉它的区域。
CSS
我们首先告诉我们的内容持有 div#ad-source 将其内容流入“命名流”。
#ad-source {
-webkit-flow-into: ads;
-ms-flow-into: ads;
}
我只在这里使用两个供应商前缀,因为这是目前唯一的支持。 我建议不要使用无前缀版本,因为这些东西在最终实现中可能会发生变化。
'ads' 是我们随意编造的任意名称。 它可以是任何东西,就像给 CSS 动画命名一样。
现在,我们设置了内容流入的区域。 首先,流入 aside,然后流入文章之间的交错 div。
aside, [class^='ad-region'] {
-webkit-flow-from: ads;
-ms-flow-from: ads;
}
在我们的示例中,在宽浏览器窗口宽度下,aside 足够大,可以容纳所有内容。 在较窄的宽度下,通过媒体查询,我们隐藏 aside,迫使内容流入 div。
[class^='ad-region'] {
display: none;
height: 155px;
width: 100%; /* Weird that this is required */
}
@media (max-width: 800px) {
[class^='ad-region'] {
display: block;
}
[class^='ad-region']:last-child {
height: 300px; /* I wish height auto worked */
}
aside {
display: none;
}
}
语义
所以,我们在周围放了一些空元素。 语义不强。 我也不确定这对可访问性有什么影响。 我确实知道 DOM 没有改变。 所有内容,无论它“流向”哪里,仍然在“源”中(具有 flow-into
属性的元素)。
不过,事情是这样的:区域是与布局样式无关的。 在这个示例中,我们仍然使用浮动进行布局,但您使用的布局样式实际上并不重要。 区域与 CSS 网格 配合使用可能更强大、更具语义(我只是不知道)。
浏览器支持
CSS 区域在Chrome 16 到 20中发布,然后在 21-22 中置于“启用 CSS 区域”标志下,现在在 Chrome 23+ 中置于“启用实验性 WebKit 功能”标志下。 它在Safari 5.2(可作为开发版或 WebKit 夜间版)中有效。 据说它在 IE 10 中有效,但我无法使其生效。
演示和下载
为了您的快乐
请注意上面的浏览器支持,它非常有限。
另请注意,在某些相当宽的浏览器窗口宽度下,aside 中的广告会被切断。 我将其保留在那里是为了说明区域不会自然地扩展高度,您需要自己考虑这一点。
浏览器检测
这种 HTML 和 CSS 本身在不支持 CSS 区域的浏览器中会很糟糕。 页面底部会随机出现一组广告。 相反,我添加了一些 JavaScript(基于此)来测试它,并根据支持情况向 html
元素应用类。
// Generic Testing Function
var supports = (function() {
var div = document.createElement('div'),
vendors = 'Khtml Ms O Moz Webkit'.split(' '),
len = vendors.length;
return function(prop) {
if (prop in div.style) return true;
prop = prop.replace(/^[a-z]/, function(val) {
return val.toUpperCase();
});
while (len--) {
if (vendors[len] + prop in div.style) {
return true;
}
}
return false;
};
})();
// Test
if ( supports('flowInto') ) {
$("html").addClass('cssregions');
} else {
$("html").addClass('no-cssregions');
}
这样,我们可以做这样的事情来确保回退正常。
#ad-source {
display: none;
}
.cssregions #ad-source {
display: block;
-webkit-flow-into: ads;
-ms-flow-into: ads;
}
此外,将 div#ad-source 的内容复制到 aside 中,以便至少在最宽的浏览器窗口宽度下,广告会出现在那里。
- 使用浏览器栏导航到 chrome://flags
- 如果您运行的是 Chrome 21 或 Chrome 22,请找到“启用 CSS 区域”标志并启用它。
- 如果您运行的是 Chrome 23 或更高版本,请找到“启用实验性 WebKit 功能”标志并启用它。
- 通过单击左下角的“立即重新启动”按钮重新启动浏览器。
如果您想将此测试添加到 Modernizr,您可以执行以下操作。
Modernizr.addTest('regions', Modernizr.testAllProps('flow-into'));
希望他们在未来的版本中将其作为一种选择添加。
我希望改进的地方
- 我希望您可以根据内容流入的容器元素样式化内容。 这可能是一个问题,因为在不同容器中的不同样式可能会导致重新流向,从而将内容推回到容器之外,从而导致无限循环的悲伤,但也许对此有一些解决方案。
- 我希望块级元素即使使用 flow-from 属性也仍然是块级元素。 很奇怪,您必须将它们设置为 width: 100%;
- 我希望 height: auto; 在具有最后一段流入内容的区域上有效。 我理解大多数流区域无法做到这一点,因为这样它们就会扩展以适合所有内容,而不是继续流入,但最后一个区域应该能够知道它剩下的内容并自然扩展。
- 我希望你能
flow-from
和flow-into
同一个元素。这样,一个语义元素就可以成为源,只有当它缩小或消失时,其他区域才会被填充。
我非常不喜欢把所有东西都塞进一列的网站。
在桌面布局(在移动设备上)我可以简单地横向滚动到页面导航。
在“响应式”中,缩放被破坏,导航离得很远,只有 100% 大小的滚动可用。
请不要为移动设备做任何事情!我喜欢缩放!
我并不完全同意你的观点。如果移动布局中禁用缩放,这意味着设计师将最大缩放比例固定为 1.0,这出于许多原因(尤其是可访问性)而不好。它似乎唯一能解决的问题是设备旋转。
但是,例如我的网站完全是响应式的,但文本和其他所有内容仍然可以缩放,因为我认为可访问性比适应用户旋转 iPad 更重要。毕竟,他们可以快速缩小,这样就能解决问题。
我同意你关于导航的观点,也许一个固定的导航栏或指向顶部的锚点链接可以考虑一下。我知道 iOS 设备在您点击顶部标题栏区域时会为您执行此操作。
这对我来说非常及时,因为我一直思考着如何在即将到来的项目中合并两个内容列表列。
正如你指出的,浏览器目前不支持这种方法,但这是一个值得关注的方法。
我目前能想到的唯一替代方案是在不同的设备宽度下使用 jQuery 动态更改 HTML。具体来说,将两列中的项目移动到一列中,然后按时间顺序排序。纯 CSS 方式更可取。
好文章!
嗨,克里斯,喜欢这篇文章。至于屏幕阅读器 - 由于 DOM 没有重新排序,这可能是一件好事,广告在底部吗?
另一个解决方案是将广告放在两个地方(侧边栏和文章之间),并根据窗口宽度显示或隐藏它们!
这真是一个巧妙的解决方法。
我同意!这是一个巧妙的想法,但它可能会成为谷歌眼中的问题,因为它可能会看到你的内容被广告覆盖!
我可能错了,但这只是我的感觉。
对于谷歌广告,我相当肯定你不允许“隐藏”广告。我相信在条款和条件中。
事实上,我喜欢这个解决方案。而且我不担心谷歌“看到一堆广告”,因为整个包含 div 甚至不会出现在最终的 html 中(我相信)。因此,谷歌只会看到一组广告。
广告投放和显示/隐藏广告的最大问题在于分析。如果使用 Omniture 和 Analytics 等工具跟踪广告,那么页面上的隐藏广告将是一件非常糟糕的事情。大多数跟踪软件会将该广告标记为效果不佳,而且它们还没有智能到足以区分隐藏广告和可见广告。
克里斯,好文章!我个人对未来感到非常兴奋 - 这种方法的更广泛应用,作为纯 CSS,将使其成为具有两列设置的网站的一个很好的补充。
很棒的网站 - 看看它很酷。但是内容折叠在我的浏览器上不能 100% 工作,因为当页面宽度小于(可能)800px 时,图像会隐藏。来自德国的问候
我之前尝试过解决这个问题,最后我决定使用 float: left 和 float: right 声明的组合。
http://jsfiddle.net/GL9sM/3/embedded/result/
这种方法的缺点是,容器只能向上延伸到其前一个兄弟元素的顶部。
我喜欢区域的未来可能性... 但支持并不存在。这似乎不像应该作为回退进行 polyfill 的事情。一开始就用 JavaScript 做吧。
对于 WordPress... 我喜欢在 loop.php(或 content.php 或其他任何内容)中添加一个广告,并输出一篇文章和一个配对的广告。然后,当宽度变得太窄时,让它们浮动到单列。这是“底部广告”解决方案,但每篇文章都有。两篇每篇文章也可以。我想我会在这个周末用客户的主题尝试一下...看看他是否喜欢。这不是广告,而是推荐。我认为这可能会很好!
顺便说一下...“交错”在 Scrabble 中得 15 分。
只是扩展了乔的想法,但你可以使用浮动和媒体查询重新创建你的广告折叠示例:http://jsfiddle.net/ympKa/embedded/result/
不错!这正是我想要编辑 WordPress 中的“循环”以输出给我的 HTML 结构。
谢谢!这个解决方案是我最终得到的:float: right/left 声明和媒体查询的组合,在达到阈值后会切换到单列布局。我只是不喜欢当第一篇文章的高度大于前两个广告的高度时,广告容器之间产生的间隙。我还没有找到解决方法...如果有任何想法,请告诉我!
哇。
这太棒了!感谢分享!
当我缩小屏幕时,广告会消失。太棒了!
我希望摆脱电视上的广告也这么容易:)
不过,没有人想缩小他们的电视:)
一如既往的棒极了
WTF?!oO
克里斯·科伊尔,CSS 的英雄!
你的评论预览是关注无关紧要的事情的完美例子。当然,这是一个很酷的小技巧,但它会让用户的打字速度慢得像蜗牛一样。
关于这篇文章...
1.) 大多数观众是屏幕分辨率足够大以容纳两列的极客。
2.) 大多数观众都是使用 Ad Block Plus 的极客。
3.) 大多数人不会坐在那里调整浏览器窗口大小来查看会发生什么。
我是不是漏掉了什么?你的三个观点都是无效的。这篇文章(以及本网站上几乎所有文章)的主要目的是与其他开发人员分享技术,以便他们在自己的项目中使用;它不是专门针对 css-tricks.com 的。
亲爱的吉米,关于这篇文章,它不是为极客的浏览器而设计的。:) 它是为我们这些为拥有各种屏幕尺寸的客户构建网站的人而设计的(不是因为他们调整了大小)。我们这些有客户没有屏蔽广告的人...
这是一个适应屏幕分辨率的创造性解决方案的实验... 以及玩转源代码顺序等等。它不是一个完美的解决方案(还没有),但我个人欢迎实验和分享。感谢克里斯!
(我不确定你的浏览器在评论预览中发生了什么,但我用 Chrome 时一点也不慢。)
祝你周末愉快!:)
谢谢,
我不知道“flow-into”一个 div
我不明白“[class^=’ad-region’]”中的上标符号和方括号。有人能解释一下这种表示法以及它是如何使用的吗?
选择所有具有以
ad-region
开头的类属性的元素。这意味着:ad-region-1
、ad-region-2
、ad-region-3
、ad-region-wow
。谢谢。现在有道理了;出于某种原因,它之前没有被理解。
在我看来,CSS 区域似乎是打破语义的完美方式。
对于这个具体的例子,比如广告(因为它们通常是固定高度),我建议在标记中交错放置它们,然后使用绝对定位在更宽的设备上将它们移到侧边栏。
这基本上是我最近一个项目中得出的解决方案 - 它运行良好,但对于具有众多/复杂模板的网站来说可能会有点问题。
不过,这是一篇好文章,我很喜欢看到解决这个问题的任何新想法。
从商业角度来说
你会发现很难说服客户调整广告大小。如果你卖给客户一个 300×250 的广告版位,它必须在所有响应式折叠/布局中保持 300 x 250 的尺寸。所以,试图向商业投资者出售这种缩放选项需要一些强大的销售技巧。
我认为横幅广告会是最大的问题。我看到的唯一解决方案是在较低分辨率下用不同尺寸的版本替换整个广告。
_jin
感谢您的教程 :)
真的很棒的解决方案。
Peter Avey
我对于占位符 div 在屏幕阅读器方面没有太大问题。当然,你可以用 JavaScript 注入它们,但 W3C 声明(HTML4 规范;在 HTML5 规范中找不到任何内容)
“我们不鼓励作者使用空 P 元素。用户代理应该忽略空 P 元素。”
标签旨在为内容提供上下文。按照这种逻辑,我认为一个空标签就像一个没有任何词语的句子。
我同意 Matthew Balaam 的观点。
无论如何,感谢您的教程!!
这很棒。这个例子适用于号召性用语,也适用于广告。
哦,我喜欢!在 Chrome 17 中运行良好。
但是,IE8 和 Firefox 中根本没有显示广告。
太棒了!感谢这些 CSS3 技巧。
您好 - 文章很棒!我是 Adobe Web 平台团队的集团产品经理,我想分享一下您希望 CSS 区域改进的地方的快速更新,因为它们已经在开发中了 :)
- 样式:我们有一个计划来支持它,事实上希望在 5 月的 CSS 面对面工作组会议上分享更新。请关注我们的博客 (blogs.adobe.com/webplatform),了解有关样式区域的实现和语法的更新。
- 块级元素和将宽度设置为 100%:这实际上是实现中的一个错误 - 对于普通流中的块,width:auto 应该对常规块计算为 100%。对于需要收缩包装的块,我们刚刚收敛了一个针对该情况的实现方法。请继续关注这些修复,以便在接下来的几周内完成。
- 设置高度:自动:这也是我们目前正在研究的内容,并在 5 月的 F2F 工作组会议后分享更新。同样,我们将在 5 月之后在我们的博客上发布更新。您可以在此处了解更多关于拟议方法的信息:http://wiki.csswg.org/spec/css3-regions/auto-height
- flow-from 和 flow-into 相同元素:经过内部讨论,工程师确认这确实应该可以工作,因为规范和实现允许这样做。它将在接下来的几周内解决。
好消息,感谢您的更新。
幸运的是,Chrome 的更新非常出色,因此我们不必担心其中较旧的、有问题的实现。
它在 Safari 5.2 中,但不幸的是,它可能有一个很长的生命周期。哦,好吧。
我将在即将到来的 WebDev 课程中尝试一下。看起来是一个很棒的解决方案。
我不确定 CSS 区域是否可以合法使用 - 所有这些关于图像上绝对定位容器的演示 - 但这很酷。内容和展示之间有一个很好的抽象级别,但空 DOM 节点会让很多纯粹主义者感到恐惧 - 有人测试过伪元素是否可以与重排一起使用吗?
是的,是的,它们可以…
感谢您,一如既往
我同意 Matthew Balaam 的观点。无论如何,感谢您的教程!!
这是一个很好的观点。我也想像那些在我们的网站上投放广告的人,他们对广告一旦变窄就被推到最底部而不会感到高兴,因为它们原本是在侧边栏顶部的优质位置,所以这很不错。
非常巧妙,并且是响应式设计的完美解决方案。我喜欢 CSS 区域。现在正在等待浏览器支持;D
抱歉,但我有一个关于同时实现两个的问题。假设您有一个网站,右侧有一列新闻提要,但新闻提要比中心页面中的内容更多。那么,有没有一种方法可以自动将一些新闻提要移动到中心页面的下方,直到您继续向中心页面添加更多文本,然后它会将新闻提要恢复到右侧列?当然用 css。
您好,它实际上很不错。但是我在将它集成到 Bootstrap Tab 内部的部分时遇到问题。它适用于活动标签,但点击另一个标签后无法使其生效。任何帮助将不胜感激!