一个经典的布局难题是如何在侧边栏中放置多少内容。理想情况下,主要内容区域和侧边栏的高度大致相同,以避免任何一个区域出现较大的空白区域,因为这看起来很奇怪,而且浪费了宝贵的网页空间。如果侧边栏内容较少,并且内容页面较短,那么可能刚刚好,但长内容页面会有很多未使用的侧边栏空间。如果侧边栏内容过多,那么长内容页面看起来不错,但短内容页面会被尴尬地向下推得较远。
一种解决方案是选择某种折衷方案,然后照此执行。另一种方法是采用技术手段,动态加载适合可用空间的适当数量的侧边栏内容。让我们看看如何做到这一点。


测试高度
我们实际上需要在这里测量内容的高度,所以这是 JavaScript 的领域。我将使用 jQuery。所以假设我们有
<section id="main-content">
</section>
<aside>
</aside>
首先,我们将“缓存”这些元素,以便我们不需要多次选择它们。
var
mainContent = $("#main-content"),
aside = $("aside");
我们将需要重复测试 aside
(侧边栏)的高度,因此我们不需要缓存该高度,但让我们为主要内容区域的高度创建一个变量,该高度不会改变。
var height = mainContent.outerHeight();
现在,我们将运行一个小测试,看看侧边栏是否有空间容纳更多内容(换句话说,其高度值是否低于主要内容区域)
if (height > aside.outerHeight()) {
// load in more sidebar content
}
加载模块
使用像 jQuery 这样的 JavaScript 库可以轻松地进行 Ajax 内容加载。如果您有一个名为 sidebarmodule.php
的文件,其中包含附加侧边栏材料的标记,您可以像这样加载它
$.get("sidebarmodule.php", function(data) {
// Create sidebar box
$("<div />", {
"class" : "sidebar-box",
"html" : data
// Fade in new module
}).hide().appendTo(aside).fadeIn();
});
但这只处理单个模块。我喜欢准备好一堆模块以根据需要插入,并将它们包含在一个文件中以简化的想法。因此,让我们使 sidebarmodule.php 更智能,并能够根据 GET 参数返回正确的模块。
<?php
$module = $_GET['module'];
if ($module > 3) { echo "No more modules"; return; }
echo "<h3>Sidebar Box #$module</h3>";
switch($module) {
case 1: ?>
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p>
<?php break;
case 2: ?>
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p>
<?php break;
case 3: ?>
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p>
<?php break;
default:
// Shouldn't ever get here, but just in case output some kind of error
echo "<p class='error'>No more modules</p>";
}
?>
现在,当我们发出 Ajax 请求以指定我们想要返回哪个模块时,我们将传递该整数参数。注意我们只创建了三个模块?让我们确保如果我们收到没有更多模块的响应,我们不会执行任何操作
var module = 1;
$.get("sidebarmodule.php", { "module": module }, function(data) {
if (data != "No more modules") {
module++;
// appending and whatnot
}
});
需要进行一些清理
当我们运行测试并验证是否有空间容纳更多模块时,我们将需要递归地发出此 Ajax 请求以获取更多模块。因此,我们将要做的是将其抽象到一个函数中,然后在需要时再次调用该函数。我们还需要确保如果我们用完了模块,递归就会停止,因此我们将设置一个 done
变量,如果我们从脚本中收到“没有更多模块”的响应,则该变量是一个停止器。
最后,我们将为高度设置一个缓冲变量。如果侧边栏仅比主要内容短 3 像素,我们实际上不需要另一个完整的模块,因此我们将此缓冲区设置为 80 像素,除非侧边栏至少短于此值,否则不会加载另一个模块。
这是整个过程
var mainContent = $("#main-content"), /* "Caching" */
height = mainContent.outerHeight(),
aside = $("aside"),
module = 1, /* Start with the first, increments */
buffer = 80, /* To prevent sidebar from growing way taller than main content if it's only barely shorter */
done = false; /* If no more modules to be had */
function getMoreContent() {
$.get("sidebarmodule.php", { "module": module }, function(data) {
if (data != "No more modules") {
// Increment # so next time it will grab a differnet module
module++;
// Create sidebar box
$("<div />", {
"class" : "sidebar-box",
"id" : "sidebar-box-" + module,
"html" : data,
"css" : {
"position": "relative",
"left": 25
}
// Fancy revealing of new content
}).hide().appendTo(aside).fadeIn(200, function() {
$(this).animate({
"left": 0
});
});
// If after getting new module, sidebar is still too short, start over
if ((height > (aside.outerHeight() + buffer)) && !done) {
getMoreContent();
}
}
});
}
// Initial test
if (height > (aside.outerHeight() + buffer)) {
getMoreContent();
}
使用说明
我还没有在这个网站上使用这个想法,但我正在考虑它,因为它是一个非常好的例子,说明哪些网站可以从中受益。其中一个考虑因素是需要 JavaScript 的内容,例如此网站上的投票。它仍然肯定可以使用,只是需要确保 JavaScript 事件绑定到传入的元素,因此需要更多一些的调整和思考。
SEO 专家也可能希望在这里发表意见。我不知道这样做的影响。Google(或其他搜索引擎)是否会看到这些动态添加的内容?我认为不会,但侧边栏内容可能并不重要,实际上 Google 不看到它可能更好(页面上与页面实际主题相关的较高百分比的内容)。
演示和下载
请注意,这里有一些 PHP 在起作用,因此不要期望将它下载到您的桌面上并使其工作,它必须位于 PHP 实际可以运行的位置。
谢谢 Chris!
这非常好,我将在我的网站上为您提供此项内容的署名。
我赞同这一点,我想看看那个教程……
我们在 Wikia 托管的所有维基上都使用动态侧边栏模块(以及页脚模块)……我们结合使用服务器端逻辑和 JS 来检测页面高度,并为内容量变化很大的页面构建美观的呈现效果(因为它们是用户生成的)。
Google 现在将索引通常仅通过 Ajax 可见的内容,这可能也是教程的另一个好主意。 :)
http://code.google.com/web/ajaxcrawling/docs/getting-started.html
在服务器端执行它也很不错。我可以想象根据文章的字数输出模块。或者可能更复杂一些,也测量图像。
—
Google 文章中的
_escaped_fragment_
内容很有趣。设置所有这些肯定需要大量的工作。看起来是 Twitter 的作品? https://twitter.com/?_escaped_fragment_=/1Password/statuses/17325144028479488
是的,在服务器端执行它,让我想起了 Jonathan Snooks 在 2007 年发表的文章,使用 CakePHP 执行此操作: http://snook.ca/archives/cakephp/elemental_conditional_content_with_cakephp
不过,我认为使用 js 实现会更有乐趣 :)
Chris,
您始终可以将所有内容加载到隐藏的部分,并使用 JS 根据高度显示/隐藏它们。
这将允许 Google 无论页面有多高都能看到所有内容,并且您不必使用 ajax :)
这听起来像是最初看到文章标题时我的想法。TechWraith,您将如何计划实施该方法?
嘿 Chris,
非常棒的想法。我遇到过这种情况很多次了。很高兴看到像这样的实用场景。
我喜欢这个想法,但我很好奇相反的方法是否更好。加载所有侧边栏内容,然后根据主要内容的高度隐藏模块。如果用户未启用 JavaScript,他们将看到所有内容,这应该也能解决 SEO 问题。它也应该会简单很多,因为您不必发出任何 AJAX 请求。
是的,我也更喜欢那样。(Y)
这样做的一个问题是,如果页面上的某些内容加载时间较长,则在加载 javascript 后,内容块将消失。这可能会让访问者想知道它去了哪里。
很棒的文章。
说实话,我非常喜欢页面内容很长时侧边栏中出现的那些空白区域。它让我能够专注于我想要查看的内容。
但是,我认为侧边栏内容长度远远超过主要内容的页面可以考虑进行裁剪。例如,您的 https://css-tricks.org.cn/contact/ 页面。
这是一个很好的观点,James
我也这么认为。我最近做了一个杂志网站移植,我使用了左侧导航栏下方的空白区域,在用户向下滚动经过侧边栏一段距离后淡入一个“返回顶部”的框;在这种情况下,比添加更多内容更好地利用了空间。
然而,这并不是要对这个技巧无端地持否定态度;它非常酷,并且在某些情况下肯定适用。(例如,在较长的页面上展示额外的广告,同时避免较短的页面出现额外的杂乱)但我确实认为,有些人倾向于填充本应留空的空白区域。
如果配合无限滚动就好了……
我真的很喜欢这个想法。一个垂直滚动的侧边栏。片段优雅地从顶部消失,整个侧边栏向上移动,同时在底部添加片段。当没有剩余片段时,从底部的片段编号一重新开始。最好保持在浏览器窗口内。当侧边栏处于焦点状态(鼠标悬停?)时,最好能够使用鼠标滚轮控制滚动。有道理吗?
我希望我能创建这样的东西。会制作一个漂亮的屏幕录制(眨眼眨眼)
向你们大家致以问候。祝大家圣诞快乐,新年快乐。
我敢打赌,滑块之类的东西会是一个好的开始……
我认为……你做得很好……但不知何故,你最好改变你的方式
这真是太棒了!在WordPress中可能还有另一种方法可以使用字数统计,然后运行一个if语句,从而避免使用JS。如果你正在使用缓存插件,那么影响应该也很小。
不过,这是一个很棒的想法 :)
我看到统计字数的问题在于你无法真正判断高度。正如Chris已经提到的,图像和其他内容在高度方面起着重要的作用。这意味着它不会那么准确。
Chris,这真是太棒了!Chris太棒了!!!!!!
非常酷的想法!而且我认为如果JS被禁用,侧边栏就不会显示任何额外的项目,所以它的降级效果很好。
题外话:我不知道你可以在jQuery中使用逗号分隔列表声明多个变量。这在传统的JS中也适用吗,还是jQuery特有的功能?
是的,这是JavaScript的东西,由jsLint建议 - “每个函数允许一个var语句”选项。我认为它看起来更简洁易读。我不确定它是否对性能有益,看看是否有人知道会很有意思?
关于原因的一篇好文章在 Nettuts+。希望这有帮助。
好技巧!!
只要留下一些舒适的“空白区域”以保持一切整洁美观,我就喜欢这个主意。
我最近看到的另一种类似的方法是修复侧边栏:当用户向下滚动页面时,侧边栏也会向下滚动。这是一个使用CSS和JavaScript完成的示例:http://xaviesteve.com/agile-scrum-google-spreadsheet-template-for-freelancers/
奇怪的是,当CSS属性发生变化时,Flash对象会“闪烁”,我想这是由于DOM被重新绘制/重新渲染造成的。
我认为最好将侧边栏中的该空间留空,因为这可以提高可读性——关注读者的需求可以建立信任,最好保持用户阅读区域的屏幕简洁。
精彩的帖子,谢谢!这种情况在移动设备上是否适用?我注意到在我的iPhone上,文本的渲染方式不同,并且由于主要内容区域中的文本渲染更大,因此侧边栏可能显得更短。我假设JavaScript会准确地检测您正在使用的设备上的高度?
再次感谢!
我最近在我的博客文章页面上实现了类似的功能。由于加载随机模块对我的网站没有意义,所以我正在加载广告。代码略有不同,但理念相同,测量内容区域并添加尽可能高的广告,最多两个广告,以填充任何存在的剩余空间。
在这里查看实际效果:http://af-design.com/blog/,然后点击任何文章。
很棒的文章,谢谢。非常喜欢使用异步调用代理来处理各种事情。
但在某些页面中包含侧边栏会存在一个问题。它会减少对页面内容的关注。访客可能会从侧边栏中的链接导航。假设我们在产品页面中包含侧边栏,人们可能会通过侧边栏链接从该页面导航,并且不会注意到产品。我从一些播客中了解到这一点,我非常同意他们的观点。
缓存jQuery对象是一个好主意,但在这种情况下,你真的不需要缓存#main-content…你只需要获取一次它的高度,所以只需存储高度即可,否则你实际上是在降低脚本的性能。
我并不完全同意这个想法,大多数情况下,当试图阅读一篇长文章时,就会出现这种“问题”,我喜欢这样一个事实:在滚动一段时间后,几乎所有干扰都被去掉了。如果我正在尝试阅读一篇长文章,侧边栏里没有任何东西是我想看的。
我认为这种东西确实有用,但不仅仅是为了填充空间而填充空间。
你好,Chris
一如既往,精彩的文章。我唯一注意到的就是你“忘记”了$代码约定:如果是jQ对象,则在var前面加上$,否则不加。
这是新东西还是只有这篇文章这样?
非常有趣的观点,评论中也有一些很好的想法。你的网站随着时间的推移变得越来越酷。 :)
一切顺利
Wolff
有些人不喜欢在jQ对象前面加上$,因为在他们看来,这太像匈牙利命名法了。
我个人已经停止遵循该约定。
我也喜欢这个想法,但前提是它不会影响主要内容。有时,尤其是在博客上,感觉就像是在雷区中穿行,试图避开广告以便阅读帖子。
我喜欢AJAX点击以显示“真实”内容或增强用户体验的其他内容的想法。
我目前正在开发一个jQuery插件,你可以使用它来标记容器,以便在向下滚动时,侧边栏中的一些重要元素更改为固定并跟随向下滚动。将它用于相关文章。
太棒了……说不出话来 :)
实际上是一篇很酷的文章!你使用什么进行代码高亮显示?
很棒的文章。感谢Chris提供的有用技巧。
这正是我正在寻找的。
我将在一些未来的项目中使用它,并确保你获得适当的认可。
感谢您发布另一篇好文章。
非常有用,谢谢 Chris!
我想从 SEO 的角度停下来一会儿。我知道一些“专家”会说这种解决方案是错误的。但是,就像你在文章最后提到的那样——侧边栏不是什么重要的事情!如果你在设计你的网站,你不应该担心“谷歌会怎么样?”。相信我,如果你创建了一个好的网站、技巧、解决方案等,用户会找到的。永远都是:)。
你好,
我不明白“done”变量在哪里被设置为 true?
可能在“if (data != “No more modules”)”中缺少一个 else 代码块?
无论如何,很棒的教程,非常有用且易于理解!
看起来我曾经尝试过使用 done 变量,但最终不需要它,也没有删除那段代码。发生的情况是,如果高度最终变得更高,它就永远不会再次调用自身,这就是它停止的方式。