在 iOS 版 Yahoo! 天气应用 的众多超级棒的设计功能中,城市屏幕之间的过渡是其中之一。 背景图像不仅会在屏幕从一个屏幕移动到另一个屏幕时移动,背景图像本身也会滑动。 它似乎隐藏了一些“旧”屏幕并揭示了“新”屏幕,这些屏幕越靠近完整视图就越明显。
让我们尝试在网络上实现它。
HTML 代码
像任何滑块一样,有三个主要组件
- 包含所有内容的容器
- 一个滑动容器,其宽度与所有幻灯片并排的宽度相同
- 每个单独的侧边容器
我们不会过多地关注幻灯片内的内容。 我只会添加温度以显示每个幻灯片确实可以在顶部容纳内容。
<div class="slider" id="slider">
<div class="holder">
<div class="slide" id="slide-0"><span class="temp">74°</span></div>
<div class="slide" id="slide-1"><span class="temp">64°</span></div>
<div class="slide" id="slide-2"><span class="temp">82°</span></div>
</div>
</div>
容器可能是一个 <section>
,幻灯片可能是一个 <article>
。 这真的取决于情况。 我会让你根据自己的需求做出语义选择。
布局方案如下

CSS 代码
“滑块”(视觉容器)和幻灯片需要具有明确相同的尺寸。 我们将在此处使用像素,但您可以使用任何方法来实现它。
.slider {
width: 300px;
height: 500px;
overflow-x: scroll;
}
.slide {
float: left;
width: 300px;
height: 500px;
}
将这些幻灯片浮动到左侧不会使它们排列成一行,因为幻灯片的父元素宽度不足以让它们这样做。 这就是我们需要占位符元素的原因之一。 它将是 300% 宽(幻灯片数量 × 100%),这将完全适合三个幻灯片。
.holder {
width: 300%;
}
我们的每个幻灯片都有一个唯一的 ID。 这样做很有用,因为如果我们选择,我们可以创建链接到这些 ID 的锚链接,并且滑块将“跳转”到这些幻灯片。 我们将添加 JavaScript 来执行一些实际的“滑动”,但即使没有它,我们的滑块也能正常工作。 ID 使此成为可能,因此让我们在此处使用它们来插入一些漂亮的背景图像。
#slide-0 {
background-image: url(http://farm8.staticflickr.com/7347/8731666710_34d07e709e_z.jpg);
}
#slide-1 {
background-image: url(http://farm8.staticflickr.com/7384/8730654121_05bca33388_z.jpg);
}
#slide-2 {
background-image: url(http://farm8.staticflickr.com/7382/8732044638_9337082fc6_z.jpg);
}
有了所有这些,我们的布局就会成形

CSS 代码(黑色渐变)
作为一个细节,根据背后的照片,以白色设置的温度可能会看不清。 为了确保它可见,我们可以使照片在底部逐渐淡化为黑色。 伪元素会很好地完成这项工作。
.slide:before {
content: "";
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 40%;
background: linear-gradient(transparent, black);
}
此处需要图片说明

JavaScript 代码(背景滑动)
我们将在此处使用 jQuery,因为我们热爱生活。 我们的目标是根据滚动调整幻灯片的背景位置。 我们可以在 CSS 中以百分比形式设置背景位置,但这本身并不能实现我们想要的酷炫隐藏/显示更多效果。 根据滚动的量(我们可以在 JavaScript 中测量),我们将调整背景位置。 单独来说,这看起来像这样
$("#slider").on("scroll", function() {
$(".slides").css({
"background-position": $(this).scrollLeft()/6-100+ "px 0"
});
});
其中的“6”和“-100”是魔法数字。 不是 容易出现脆弱性的 CSS 魔法数字,而是传统的魔法数字。 只是一些恰好使效果起作用的数字。 或许很糟糕,但这并不是什么大不了的事情。 设计方面的事情有时就是这样。 也许最好在代码中添加一个注释来解释这一点。 这些特定的数字基于我使用的图像及其大小以及看起来不错的内容。
此处的效果是我们想要的背景移动

JavaScript 代码(赋予结构)
这段小小的 JavaScript 代码看起来很孤独,因为它没有背后的结构。 滑块是查看结构化 JavaScript 的简单方法的一个很好的借口。
我们可以将所有与滑块相关的内容都设为一个对象。
var slider = {
};
然后,我们将相关元素组合到一个区域中,将我们的事件绑定在一起,并编写执行非常特定任务的小函数。
var slider = {
el: {
slider: $("#slider"),
allSlides: $(".slide")
},
init: function() {
// manual scrolling
this.el.slider.on("scroll", function(event) {
slider.moveSlidePosition(event);
});
},
moveSlidePosition: function(event) {
// Magic Numbers
this.el.allSlides.css({
"background-position": $(event.target).scrollLeft()/6-100+ "px 0"
});
}
};
slider.init();
HTML 代码(添加导航)
添加滑动功能会非常(非常)酷(提示)。 但现在,让我们添加一些可点击的链接来更改幻灯片,而不是依赖滚动条。 在现实生活中,您甚至可以删除滚动条(直接对容器使用 overflow: hidden;)。 我们需要的是链接到各个幻灯片 ID 的锚链接。
<nav class="slider-nav">
<a href="#slide-0" class="active">Slide 0</a>
<a href="#slide-1">Slide 1</a>
<a href="#slide-2">Slide 2</a>
</nav>
随意设置样式。 对于 演示,我将它们设置为带隐藏文本的小灰色圆圈。
JavaScript 代码(添加导航)
我们的结构现在更有用。 我们只需添加我们正在处理的其他几个元素,添加一个我们正在监听的新事件(单击导航),并编写一个处理该事件的小函数。
我们知道从链接本身的 ID 可以知道单击导航链接时滚动位置的动画移动距离。 该链接可能是 href=”#slide-1″,我们可以轻松地从中获取“1”。 然后我们需要滚动到的位置是(1 × 幻灯片宽度),在本例中为 300。 我们将在 JavaScript 中存储该 300 值。
var slider = {
el: {
slider: $("#slider"),
allSlides: $(".slide"),
sliderNav: $(".slider-nav"),
allNavButtons: $(".slider-nav > a")
},
timing: 800,
slideWidth: 300, // could measure this
init: function() {
// You can either manually scroll...
this.el.slider.on("scroll", function(event) {
slider.moveSlidePosition(event);
});
// ... or click a thing
this.el.sliderNav.on("click", "a", function(event) {
slider.handleNavClick(event, this);
});
},
moveSlidePosition: function(event) {
// Magic Numbers
this.el.allSlides.css({
"background-position": $(event.target).scrollLeft()/6-100+ "px 0"
});
},
handleNavClick: function(event, el) {
// Don't change URL to a hash, remove if you want that
event.preventDefault();
// Get "1" from "#slide-1", for example
var position = $(el).attr("href").split("-").pop();
this.el.slider.animate({
scrollLeft: position * this.slideWidth
}, this.timing);
this.changeActiveNav(el);
},
changeActiveNav: function(el) {
// Remove active from all links
this.el.allNavButtons.removeClass("active");
// Add back to the one that was pressed
$(el).addClass("active");
}
};
slider.init();
我们在导航链接上有一个“active”类,仅用于在 CSS 中用于视觉上指示哪个幻灯片处于活动状态。 我们通过从所有链接中删除“active”,然后将其添加到被单击的链接中来处理它。
演示!
Check out this Pen!
太棒了!
我现在想到的下一件事是,是否有一种方法可以动态地引入 Flickr 照片。
我希望我能“点赞”这个哈哈。
Flickr 提供了一个 API: http://www.flickr.com/services/api/
太棒了! 触摸和滑动检测将是完美的点睛之笔(双关语)。
简单,很棒。 谢谢!
哦,太棒了。 非常棒的教程。
刚刚在 Windows Phone 上测试过,触摸滑动效果很好…… 谢谢!
一个美妙、美味且微妙的效果。 谢谢分享。 不幸的是,我并没有完全理解“魔法数字”的概念。 我希望有人能给我解释一下。
“神奇数字”是指那些不是通过程序找到的数字——你只需要尝试一下,找出哪些数字能产生你需要的效果。在本例中,将元素背景位置设置为左侧距离 (scrollLeft()) 除以 6 再减 100,可以让效果看起来更好(对设计师而言)。
这很棒。你甚至可以很容易地添加额外的图像,只需做一些改动。但你认为有没有办法在触摸屏设备上滑动图像时强制它们自动居中于框架中?这样就完美了。
感谢你辛勤工作,为我们提供精彩的文章。
这是一篇很棒的教程……我爱它。
将容器的宽度设置为容器百分比(300%)非常棒。你可以对幻灯片做同样的事情——如果你有三个幻灯片,每个幻灯片将占容器的 33.333…%。使用足够的有效位数,以便在目标设备分辨率上实现亚像素精度,并且不会出现溢出(总和大于 100%)。
一个更好的解决方案,可以使其灵活(在设计和内容方面)
.slider {
height: 100%;
overflow-x: scroll;
-webkit-overflow-scroll: touch;
.holder {
height: 100%;
white-space: nowrap
}
.slide {
display: inline-block
width: 100%;
height: 100%;
}
这样,你就可以拥有任意数量的项目。如果你不想要全屏,就在 .slider 中添加固定值。
一个无需 jQuery 的解决方案,也支持自动滚动到“活动”项:http://codepen.io/Merri/pen/fdAaI
JavaScript 有很好的注释,但你需要很好地理解闭包才能理解它是如何工作的。
这正是我要说的。
感谢 Vesa Piittinen。
我现在已经对代码进行了重构,并添加了一些新功能,例如鼠标滚轮支持和淡入效果。代码现在始终知道当前幻灯片,并为其设置活动类。做了一些优化,但效果的混合可能会对某些设备造成一些负担(盒阴影和文本阴影与多级不透明度的可能性)。
非常棒,Vesa。我假设你支持滑动事件。我现在没有支持它的设备。
您好,Vesa,
我刚在 Nexus 7 上测试了你的代码,运行得很好,有点卡顿,但这可能是你提到的所有效果造成的。然而,不知何故,我无法在第二个滑块上滑动,但第一个可以。是第一个有链接而第二个没有吗?
Chris,
最近做了很多类似的事情,我意识到一个比
更干净的替代方案是
其中你的锚点可能是
显然,这种替代方案在教程的背景下只稍微好一点,但一旦你拥有大量 JavaScript 或复杂的情况,用这种方式做事会让生活变得轻松很多。
其他一切都完美无缺。这是一个很棒的教程。
var position = $(el).attr("data-index");
也可以简化为
var position = $(el).data("index");
Oliver,jQuery data 方法与使用 HTML5 data 属性不同。
http://stackoverflow.com/questions/7261619/jquery-data-vs-attr
具有讽刺意味的是,我一直致力于一个 jQuery “插件”,用于延迟加载背景图像。https://gist.github.com/yramagicman/5602693
目前,它不支持滚动,但我正在努力解决这个问题。
你总是可以避免神奇数字。但这需要更多时间来弄清楚
” $(event.target).scrollLeft()/6-100 ” 来自哪里。我今天实际上做了一些类似的事情。我使用 jQuery 获取视窗宽度、带边距的元素宽度等等。最终得到了一个不漂亮的公式……但是……没有神奇数字,并且响应式工作 :)
你可以使用这段 JavaScript 代码来节省 41% 的原始大小,这使其更快。
var slider={el:{slider:$("#slider"),allSlides:$(".slide"),sliderNav:$(".slider-nav"),allNavButtons:$(".slider-nav > a")},timing:800,slideWidth:300,init:function(){this.bindUIEvents()},bindUIEvents:function(){this.el.slider.on("scroll",function(a){slider.moveSlidePosition(a)});this.el.sliderNav.on("click","a",function(a){slider.handleNavClick(a,this)})},moveSlidePosition:function(a){this.el.allSlides.css({"background-position":$(a.target).scrollLeft()/6-100+"px 0"})},handleNavClick:function(a,b){a.preventDefault(); var c=$(b).attr("href").split("-").pop();this.el.slider.animate({scrollLeft:c*this.slideWidth},this.timing);this.changeActiveNav(b)},changeActiveNav:function(a){this.el.allNavButtons.removeClass("active");$(a).addClass("active")}};slider.init();
很棒的图形,但是编辑 CSS 代码的最佳 Word 文档是什么?我使用的是 Notepad,它运行良好。任何想法都将不胜感激。
哇!这是一个非常棒的效果。我爱它!
代码写得很好……我尝试了在滑块中添加更多图片,它运行得很好。
看起来很棒,谢谢。
太美了
像往常一样精彩的文章,Chris。谢谢!
很棒的文章和示例。有人能告诉我如何让滑块自动移动,并在鼠标悬停在图像上时停止吗?提前感谢。
这真的很酷,我特别喜欢你总是挑战自己进行这类实验,只为了挑战自己!谢谢!
好吧,又一次从 CSS Tricks 中获得灵感……在连续长时间处理表单和有时毫无意义的活动后,你的作品带来了新鲜的空气和想法,我迫不及待地想尝试……很高兴看到如何在 JS 中大量使用其他优秀功能之间应用对象字面量表示法,感谢分享
非常棒,有很多 CSS Tricks,但这个简单却令人惊叹。:)
不错的教程,但我无法让锚点起作用,布局也有些混乱,直到我向幻灯片 (.slide) 添加了“position: relative”,我猜这是由于叠加的渐变元素造成的。
性感的代码在这里!
我见过它在网站背景上实现……
感谢你,我一直在寻找一些东西来让我的背景稍微滑动一下,
css-tricks 真棒
我想最好将 overflow-x 选项设置为 hidden。
是的!!!我一直在想如何在下面隐藏那个笨重的滚动条。谢谢,Andrés。
看起来超级酷。触摸滑动使其更加棒。
嘿,很棒的东西!运行良好,但是当我将尺寸更改为(例如)900 宽度和 300 高度时,它会变得有点混乱。它是否与 6-100 有关?
这超级性感。滑动在我的运行 Firefox 的 Android 2.3.6 手机上可以工作。我想在重新设计我的网站时会使用它。:-)
为什么是滑动背景而不是图像?用 img 标签和位置做同样的事情应该很容易。
Fork 它,去做吧。
我一直遵循的规则是,如果它用作背景图像,就将其作为 CSS 规则,并将图像存储在 css/images 文件夹中。 如果它是一个内容图像(徽标、产品、图库图片等),它将被放置在一个 img 标签中。 这有点吹毛求疵,但这是我学习整理文件系统的方式,它对我来说在语义上是有意义的。
在这种情况下,图像用作背景图像,那么为什么要将其放在图像标签中并添加额外的 CSS 来定位,而您可以让标记自然流动呢?
如果我复制粘贴 HTML 代码使其出现两次,当我使用第一个滑块上的滚动条时,它也会移动第二个滑块。 但反之则不然。
如果我有 3 个滑块,滚动第一个将移动所有 3 个,但滚动第二个,将不会移动第三个。
这太棒了! 我将用它来替换我正在使用的 RoyalSlider。 我想知道添加“上一个”和“下一个”按钮以进行导航有多容易……
好奇,如果这被转换为使用百分比,视差效果会消失吗?(100% 屏幕宽度)
我对 Javascript/Jquery 非常陌生,偶然发现了这个教程,并想尝试一下。
所以我复制粘贴了 Demo 中提供的 HTML、CSS 和 JS 代码,HTML 和 CSS 工作正常,但我就是无法让 JS 工作,也无法弄清楚它为什么不工作,一定是 我在 HTML 中做了一些事情(或没有做)。 因为所有的代码在 Demo 中显然都工作正常。
目前我正在尝试使用外部 JS 文件,在 HTML 的 head 部分使用以下代码。 正如我所说,我对这方面非常陌生,而且可能把所有事情都搞错了。
任何人都可以给像我这样的新手一些建议来让它工作吗?
我遇到了同样的问题,除了 javascript 之外,一切都工作正常,无论我是在头部放置代码还是链接到 .js 文件。 有没有人知道可能出了什么问题?
我相信你需要在 HTML 文档的头部导入 jQuery 库,以便 JS 文件正常工作,方法是链接到最新的托管版本,或者下载它,然后将其放到你的 Web 服务器上。
这里有两种方法的说明以及可下载文件。
感谢您的详细解释。
这太棒了! 它对我来说完美地工作。
现在我想为此添加两个功能
1) 导航子弹可以跟随触摸滚动更新(点击子弹没有问题)。
2) 自动播放。
如果有人知道如何做到这一点,请告诉我。 谢谢~
在我们网页设计公司,我们永远不会创建无限滚动的内容页面。 这是现代网站设计中一种非常过时且没有创意的方式。
嗨,Chris,感谢您提供这个很棒的代码片段。 我注意到的一件事是——当我从 CODEPEN 复制代码并在本地重新创建文件时——不知何故,平滑度消失了? 我做错了什么?
感谢您的帮助。
我遇到了同样的问题几个小时,直到我把它上传到我的互联网服务器,然后 js 的平滑滑动功能优雅地工作了!(虽然,我的照片的大小不同是另一个故事。:/)
嘿,Chris,这看起来很棒(结果),但我自己尝试时,javascript 对我不起作用,我认为问题是我不知道如何使用 javascript,你能告诉我需要包含的 css 和 js 文件的代码吗?
再次问好,添加了以下两行代码后,一切正常,真的很棒!! 迄今为止一切顺利,仍然希望得到一些东西,如何使它(滑动)在,比如 10 秒后自动发生!!
“两行代码”是……?
嘿,Chris
我只是想让这段代码运行。 html 和 css 工作正常,但是我似乎无法让图像上的滑动动画工作。 我只能想到我没有引用正确的 jQuery 源代码。 我需要在哪些链接中包含哪些内容才能加载 jQuery 库?