滑动页眉布局

SlidingMain

Today we’d like to show you how to create a simple grid layout with a special header effect. The idea is to initially show a fullscreen image with a title and a toggle button that allows to change the view to a grid. The header with the fullscreen image animates upwards and reveals a grid of image anchors with a title. We’ll be using some techniques like Flexbox and CSS Transitions for modern browsers. For the trigger button that toggles the views, we’ll create a vector graphic with two groups, one containing a little grid and the other one containing a cross. These two groups will have their visibility toggled according to the current view (fullsreen header or grid).

今天,我们想向您展示如何创建具有特殊标题效果简单网格布局。 最初的想法是显示全屏图像,其中包含标题和切换按钮,可将视图更改为网格。 具有全屏图像的标题向上移动,并显示带有标题的图像锚点网格。 我们将为现代浏览器使用诸如Flexbox和CSS Transitions之类的技术。 对于切换视图的触发按钮,我们将创建一个包含两组的矢量图形,一组包含一个小网格,另一组包含一个十字。 这两个组的可见性将根据当前视图(fullsreen标头或网格)进行切换。

Sliding01

The inspiration for the layout and the effect come from this fabulous Dribbble shot by Dann Petty: iPad Magazine – Table of Contents

布局和效果的灵感来自Dann Petty拍摄的这张精彩的Dribbble: iPad杂志–目录

Web technologies we’ll be using in this tutorial:

本教程将使用的Web技术:

The beautiful images used in the demo are by Dan Rubin. Find him on Instagram, Twitter, Flickr and VSCO. Please don’t use the images without his permission.

该演示中使用的精美图像是Dan Rubin制作的 InstagramTwitterFlickrVSCO上找到他。 未经他的许可,请勿使用这些图像。

The grid will be laid out using Flexbox and we’ll control the number of items and their height with specific media queries and by using Viewport Units. Using the same vw values for the width and height (more specifically, for the flex-basis and the height) of the grid item, we can create an adaptive layout where we keep the proportions of the anchor/image close to a square. There are of course other techniques for doing this but let’s explore the relative viewport units in combination with a Flexbox layout today. If you’d like to know more about the support, we recommend Can I Use, the go-to site for browser support info and stats.

网格将使用Flexbox进行布局,我们将通过特定的媒体查询以及使用视口单位来控制项目的数量及其高度。 使用相同的vw值来表示网格项目的宽度和高度(更确切地说,是基于柔韧性和高度),我们可以创建一个自适应布局,使锚点/图像的比例保持接近正方形。 当然,还有其他技术可以做到这一点,但让我们今天结合Flexbox布局探索相对视口单位。 如果您想了解有关支持的更多信息,我们建议您访问我的网站,该站点提供浏览器支持信息和统计信息。

Sliding02

So, let’s get started!

所以,让我们开始吧!

标记 (The Markup)

Let’s think for a moment, what blocks we’ll need for our little layout. We’ll need a header with an image and a title block, and we’ll need a main content block with a grid. Everything should be wrapped in a container that we’ll use to control what’s happening by toggling a view class.

让我们考虑一下,我们的小布局需要哪些块。 我们需要一个带有图像和标题块的标题,并且需要一个带有网格的主要内容块。 一切都应该包装在一个容器中,我们将通过切换视图类来控制正在发生的事情。

Let’s build the header in the following way:

让我们通过以下方式构建标题:


<header class="intro">

	<img class="intro__image" src="img/header.jpg" alt="Iceland glacier"/>

	<div class="intro__content">

		<h1 class="intro__title">Essential Feelings</h1>

		<div class="intro__subtitle">

			<div class="codrops-links">
				<!-- links -->
			</div>

			<div class="intro__description"> <!-- ... --> </div>

			<button class="trigger">

				<svg width="100%" height="100%" viewBox="0 0 60 60" preserveAspectRatio="none">
					<g class="icon icon--grid">
						<rect x="32.5" y="5.5" width="22" height="22"/>
						<rect x="4.5" y="5.5" width="22" height="22"/>
						<rect x="32.5" y="33.5" width="22" height="22"/>
						<rect x="4.5" y="33.5" width="22" height="22"/>
					</g>
					<g class="icon icon--cross">
						<line x1="4.5" y1="55.5" x2="54.953" y2="5.046"/>
						<line x1="54.953" y1="55.5" x2="4.5" y2="5.047"/>
					</g>
				</svg>

				<span>View content</span>

			</button>

		</div><!-- /intro__subtitle -->

	</div><!-- /intro__content -->

</header><!-- /intro -->

The header gets the class “intro”. The fullscreen image is the first child with the class “intro__image”. What follows is the intro content that contains the main title and a subtitle with three elements: some links, a description and the trigger button. The trigger button is a vector graphic that we have created previously. It consists of two shape groups: a grid and a cross. We give them suitable class names and we’ll control their appearance with a class that we’ll toggle in our script.

标头获得类“介绍”。 全屏图像是“ intro__image”类的第一个孩子。 以下是介绍性内容,其中包含主要标题和带有三个元素的副标题:一些链接,描述和触发按钮。 触发按钮是我们先前创建的矢量图形。 它由两个形状组组成:网格和十字形。 我们给它们合适的类名,并使用将在脚本中切换的类来控制它们的外观。

Next, we need to create the markup for our grid. For that we’ll have a main container and a wrapper for the grid anchors:

接下来,我们需要为我们的网格创建标记。 为此,我们将有一个主容器和一个用于网格锚的包装器:


<section class="items-wrap">

	<a href="#" class="item">
		<img class="item__image" src="img/item01.jpg" alt="item01"/>
		<h2 class="item__title">Magnificence</h2>
	</a>

	<a href="#" class="item">
		<img class="item__image" src="img/item02.jpg" alt="item02"/>
		<h2 class="item__title">Electrifying</h2>
	</a>

	<!-- ... -->

</section><!-- /items-wrap -->

You can also use a list here if you like and wrap each anchor into a li, or a figure element. We choose to spare the extra markup and keep it simple.

如果愿意,还可以在此处使用列表,并将每个锚点包装到li或Figure元素中。 我们选择保留多余的标记并使之简单。

So, that’s our HTML. Let’s get to the juicy CSS.

因此,这就是我们HTML。 让我们来看看多汁CSS。

CSS (The CSS)

Note that we don’t use vendor prefixes here, but you can of course find them in the stylesheet files.

请注意,这里我们不使用供应商前缀,但是您当然可以在样式表文件中找到它们。

Let’s revise what exactly we want to achieve with our layout and what effects we want to happen:

让我们修改一下我们想要通过布局实际实现的功能以及想要发生的效果:

  1. The header should occupy the full screen initially and the title area should be shown at the bottom of this intro page.

    标题最初应占据全屏,标题区域应显示在此简介页的底部。
  2. When the trigger button is clicked

    单击触发按钮时

    • the intro should slide up and be 250px of height while darkening and the image should move down a bit so that we create a slight parallax effect

      简介应该向上滑动并变黑,高度为250px,图像应该向下移动一点,以便我们产生轻微的视差效果
    • the content should be revealed with an overlay effect simulating light entering the dark content area

      内容应具有叠加效果,以模拟进入黑暗内容区域的光来显示
    • the trigger button should change from a grid icon to a closing cross

      触发按钮应从网格图标变为十字形
  3. The grid items in the content area should have a hover effect where the title fades out while moving down and the images zooms a bit and becomes brighter.

    内容区域中的网格项目应具有悬停效果,标题在向下移动时会逐渐消失,图像会稍微放大并变亮。

In order to achieve the main effects, we’ll have to define the default states of the elements/blocks and the states when the grid is shown.

为了实现主要效果,我们必须定义元素/块的默认状态以及显示网格时的状态。

Note that some default styles will be predefined and we’re not going to mention them here as it’s something you might want to adjust by yourself (body, default anchor styles and colors). We usually define those in our demo.css where we also set the box-sizing to border-box. Additionally, we also use Normalize.css.

请注意,一些默认样式将是预定义的,在这里我们不再赘述,因为您可能需要自行调整(主体,默认锚样式和颜色)。 我们通常在demo.css中定义它们,然后将box-sizing设置为border-box。 此外,我们还使用Normalize.css

Let’s start by styling the header. We want it to occupy all the width and height of the screen and detach it from the rest of the content layout, so let’s define the dimensions as well as its position (fixed). We’ll set the overflow to hidden because we don’t want anything to stick out, in particular, the image. For the sliding effect, we’ll add a transition and a nice easing function. When we add the class for opening the content area, i.e. container–open, on the main container, we will set the transform of the intro. We use two translate3d transforms: the first one will move it up completely (100% of its own height) and the second one will move it down 250px which is the final height we want for our header. (We could as well use just one transformation on the Y-axis and say calc(-100% + 250px) but transitioning to that won’t work in IE.)

让我们开始设计标题。 我们希望它占据屏幕的所有宽度和高度,并将其与内容布局的其余部分分离,因此让我们定义尺寸及其位置(固定)。 我们将溢出设置为隐藏,因为我们不希望任何东西特别是图像突出显示。 对于滑动效果,我们将添加一个过渡和一个不错的缓动函数。 当我们在主容器上添加用于打开内容区域的类(即container-open )时,我们将设置介绍的转换。 我们使用了两个transform3d转换:第一个将其完全向上移动(其自身高度的100%),第二个将其向下移动250px,这是我们想要的标头的最终高度。 (我们也可以只在Y轴上使用一种转换,并说calc(-100%+ 250px),但在IE中过渡到该转换将无效。)


.intro {
	position: fixed;
	z-index: 10;
	overflow: hidden;
	width: 100%;
	height: 100%;
	background: #2a2e39;
	transition: transform 0.6s;
	transition-timing-function: cubic-bezier(0.7, 0, 0.3, 1);
}

.container--open .intro {
	transform: translate3d(0, -100%, 0) translate3d(0, 250px, 0);
}

The fullscreen intro image will to be positioned absolutely and we’ll set the minimum height to 120% of its parent because we want to translate it 20% up. Setting the opacity to 0.8 will make the background color of our header shine through a bit. We should use the same easing function for the image and also the same time. This will make the effect feel more natural by syncing the acceleration of the elements. When we set the opening class to the main container, we’ll make the image completely transparent and translate it 20% down.

全屏介绍图片将绝对定位,我们将最小高度设置为其父高度的120%,因为我们要将其向上平移20%。 将不透明度设置为0.8,将使标题的背景颜色略微发光。 我们应该对图像使用相同的缓动功能,并且同时使用相同的缓动功能。 通过同步元素的加速度,可以使效果更加自然。 当我们将打开类设置为主容器时,我们将使图像完全透明并将其向下转换20%。


.intro__image {
	position: absolute;
	bottom: 0;
	min-width: 100%;
	min-height: 120%;
	width: auto;
	height: auto;
	opacity: 0.8;
	transition: transform 0.6s, opacity 0.6s;
	transition-timing-function: cubic-bezier(0.7, 0, 0.3, 1);
}

.container--open .intro__image {
	opacity: 0;
	transform: translate3d(0, 20%, 0);
}

The style for the intro content is the following. We’ll stuck it to the bottom of its parent and set a padding along with an enlarged font size.

介绍内容的样式如下。 我们将其粘贴到其父级的底部,并设置填充和扩大的字体大小。


.intro__content {
	position: absolute;
	bottom: 0;
	padding: 1.8em;
	width: 100%;
	font-size: 1.15em;
}

The style for the intro content is the following. We’ll stuck it to the bottom of its parent and set a padding along with an enlarged font size. Note that some default styles are predefined and we’re not going to mention them here as it’s something you might want to adjust by yourself (body, default anchor styles and colors).

介绍内容的样式如下。 我们将其粘贴到其父级的底部,并设置填充和扩大的字体大小。 请注意,一些默认样式是预定义的,在这里我们不再赘述,因为这是您可能要自行调整的内容(主体,默认锚样式和颜色)。


.intro__title {
	margin: 0 0 20px;
	font-weight: 900;
	font-size: 4em;
	font-family: "Playfair Display", Georgia, serif;
	line-height: 1;
}

For the subtitle which contains the links, the description and the trigger button, we will use a flexbox layout. For that, we define the flex display on the parent. Setting align-items to center will center the children on a horizontal line. This kind of centering can also be achieved by setting the children to display: inline-block and their vertical-align to middle. But that’s the only useful thing we can do with that display value. Flexbox can do so much more for us.

对于包含链接,描述和触发按钮的字幕,我们将使用flexbox布局。 为此,我们在父级上定义了弹性显示。 将align-items设置为居中将使子项在水平线上居中。 也可以通过将子级设置为显示来实现这种居中:内联块并将其垂直对齐到中间。 但这是我们可以利用该显示值进行的唯一有用的操作。 Flexbox可以为我们做更多的事情。


.intro__subtitle {
	display: flex;
	align-items: center;
}

For example, we can push the trigger button to the right end by simply setting the right margin of the description to auto. Simply beautiful. No widths set, no floats, just awesome flexbox.

例如,我们可以通过简单地将描述的右边距设置为auto来将触发按钮推到最右端。 简单的美丽。 没有设置宽度,没有浮动,只是很棒的flexbox。


.intro__description {
	margin: 0 auto 0 1em;
	line-height: 1.2;
}

Next, let’s style our trigger button. So, we have an inline SVG where we’ve set the following attributes:

接下来,让我们设置触发按钮的样式。 因此,我们有一个内联SVG,我们在其中设置了以下属性:


<svg width="100%" height="100%" viewBox="0 0 60 60" preserveAspectRatio="none"><!-- ... --></svg>

Setting the preserveAspectRatio to none will stretch/shrink our graphic to any dimension. It happens that we made a 60×60 sized icon but we actually want it to be a bit smaller. No problem, we simply set the desired width and height to its parent. Note that we set the flex value to none here because we don’t want the icon to be squeezed when we don’t have so much space.

设置preserveAspectRationone会将我们的图形拉伸/缩小到任意尺寸。 碰巧我们制作了一个60×60大小的图标,但实际上我们希望它要小一些。 没问题,我们只需为其父级设置所需的宽度和高度即可。 请注意,我们在此处将flex值设置为none,因为我们不希望在没有太多空间时挤压图标。


.trigger {
	position: relative;
	overflow: hidden;
	margin: 0 0 0 20px;
	padding: 0;
	width: 40px;
	height: 40px;
	outline: none;
	border: none;
	background: none;
	flex: none;
}

Let’s hide the button text but leave it accessible:

让我们隐藏按钮文本,但使其可访问:


.trigger span {
	position: absolute;
	top: 100%;
}

We want the shapes to have a stroke and no fill:

我们希望形状具有笔触且没有填充:


.icon rect,
.icon line {
	stroke: #dbdbdb;
	fill: none;
	stroke-width: 2px;
}

Note that when you resize a SVG you’ll have to take that into consideration when defining the stroke width. We’ve shrunk our icon so we need to set a stroke-width of 2 in order to look decent.

请注意,调整SVG大小时,在定义笔触宽度时必须考虑到这一点。 我们缩小了图标,因此我们需要将笔划宽度设置为2才能看起来不错。

The icon groups will have a transition:

图标组将进行过渡:


.icon {
	transition: opacity 0.3s, transform 0.3s;
	transform-origin: 50% 50%;
}

And we’ll hide the grid icon and show the cross when activating the button (by scaling and fading them in/out). This active class we’ll set in our script.

我们将隐藏网格图标并在激活按钮时显示十字(通过缩放和淡入/淡出它们)。 我们将在脚本中设置此活动类。


.icon--cross,
.trigger--active .icon--grid {
	opacity: 0;
	transform: scale3d(0.5, 0.5, 1);
}

.trigger--active .icon--cross {
	opacity: 1;
	transform: scale3d(1, 1, 1);
}

And that’s the styling for the header. Now, let’s write the styles for the main content section.

这就是标题的样式。 现在,让我们为主要内容部分编写样式。

The wrap for the items which are anchors with images will have a flex display. Because we want a grid layout, we’ll wrap the items. We’ll set the top padding to the height of the intro header when the content is open.

带有图像的锚定项的包装将具有弹性显示。 因为我们需要网格布局,所以我们将包装它们。 当内容打开时,我们将顶部填充设置为简介标题的高度。


.items-wrap {
	position: relative;
	display: flex;
	flex-wrap: wrap;
	padding: 250px 5px 0;
}

For the brightening effect, we’ll use the ::after pseudo-element of the wrap and animate its opacity from 1 to 0 using the same duration and timing-function as before:

为了获得增亮效果,我们将使用:: ::伪包装元素,并使用与之前相同的持续时间和计时功能,将其不透明度从1设置为0:


.items-wrap::after {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	background: #2a2e39;
	content: '';
	opacity: 1;
	transition: opacity 0.6s;
	transition-timing-function: cubic-bezier(0.7, 0, 0.3, 1);
	pointer-events: none;
}

.container--open .items-wrap::after {
	opacity: 0;
}

The grid items will be flexible and we’ll set the flex-basis to a default of 25% because we want to show 4 items in a row (later we’ll define some media queries for displays that are equal/smaller than laptop size). What’s interesting here is the height. By using a height that is relative to the viewport width we can actually ensure that our grid item is close to a square. We don’t set 25vw here because we need to subtract some of the space so we set a value that looks good for a range of display widths. This combination works because our layout is close to full width. You could also play with viewport units for the flex-basis instead of percentages which will give you the same results considering that you subtract the other widths like item borders and paddings of the parent. This is one possible technique and playing with it gives some insight on how useful viewport units can be. You could achieve this in different ways (think padding-hack) but today we want to play with viewport units and flexbox to create our fluid grid.

网格项目将很灵活,我们将flex-basis设置为默认值25%,因为我们希望连续显示4个项目(稍后,我们将为显示器定义一些媒体查询,这些查询等于/小于笔记本电脑的尺寸)。 有趣的是高度。 通过使用相对于视口宽度的高度,我们实际上可以确保我们的网格项目接近正方形。 我们此处未设置25vw,因为我们需要减去一些空间,因此我们设置的值对于一定范围的显示宽度来说看起来不错。 这种组合之所以有效,是因为我们的布局接近全宽。 考虑到减去其他宽度(如项目边框和父级的填充),您也可以使用弹性基础的视口单位代替百分比,这将给您相同的结果。 这是一种可能的技术,并且通过使用它可以了解有用的视口单元的数量。 您可以通过不同的方式(例如padding-hack)来实现这一目标,但是今天我们想使用视口单元和flexbox来创建流体网格。


.item {
	position: relative;
	overflow: hidden;
	height: 22vw;
	flex: 1 0 25%;
	outline: none;
	border: 5px solid #2a2e39;
	border-width: 0 5px 10px;
	background: #2a2e39;
}

The image will be positioned absolutely and we’ll center it vertically by setting the top to 50% and pulling it up by half of its own height using a 3D transform. Additionally we’ll scale it up by default and set it to be slightly transparent. When hovering, we’ll make it opaque and remove the scaling, making it zoom out to its original dimensions.

图像将被绝对定位,我们将顶部设置为50%,并使用3D变换将其向上拉高一半,以使其垂直居中。 此外,默认情况下,我们会将其放大并设置为稍微透明。 悬停时,我们将使其变得不透明并移除缩放比例,使其缩小至原始尺寸。


.item__image {
	position: absolute;
	top: 50%;
	left: 0;
	min-height: 100%;
	width: 100%;
	opacity: 0.7;
	transition: transform 0.5s, opacity 0.5s;
	transform: translate3d(0, -50%, 0) scale3d(1.2, 1.2, 1);
}

.item:hover .item__image {
	opacity: 1;
	transform: translate3d(0, -50%, 0);
}

Note that you could also use a different color or gradient for the background of the item to create a unique look and mood for the images. If you’d like to give some visual feedback for users tabbing through the grid, you can also add a .item:focus style. The title will also be positioned absolutely at the bottom of the element. When we hover the anchor, the title will fade out while moving down.

请注意,您还可以为项目的背景使用不同的颜色或渐变,以为图像创建独特的外观和风格。 如果您想为用户提供一些视觉上的反馈,请用户在网格中.item:focus ,也可以添加.item:focus样式。 标题也将绝对位于元素的底部。 当我们悬停锚点时,标题将在向下移动时淡出。


.item__title {
	position: absolute;
	bottom: 0;
	margin: 0;
	padding: 1em;
	color: #dbdbdb;
	font-size: 1.85em;
	font-family: "Playfair Display", Georgia, serif;
	line-height: 1;
	transition: transform 0.3s, opacity 0.3s;
}

.item:hover .item__title {
	opacity: 0;
	transform: translate3d(0, 20px, 0);
}

Finally, we want our grid to change the number of items in a row depending on the size of the screen. We also want to adjust the font-size for smaller viewports. Experimenting with different heights for the items we can make the layout look as we want and setting the right flex-basis will control the amount of items:

最后,我们希望网格根据屏幕尺寸来更改连续的项目数量。 我们还想为较小的视口调整字体大小。 尝试使用不同高度的项目,我们可以使布局看起来像我们想要的,并设置正确的flex-basis将控制项目的数量:


/* Media Queries */
@media screen and (max-width: 1440px) {
	.item {
		height: 30vw;
		-webkit-flex: 1 0 33.333%;
		flex: 1 0 33.333%;
	}
}

@media screen and (max-width: 1000px) {
	.item {
		height: 45vw;
		-webkit-flex: 1 0 50%;
		flex: 1 0 50%;
	}
	.item,
	.intro__content {
		font-size: 0.85em;
	}
}

@media screen and (max-width: 590px) {
	.item {
		height: 90vw;
		-webkit-flex: 1 0 100%;
		flex: 1 0 100%;
	}
}

And that’s all the style. Next, let’s write a little script.

这就是所有样式。 接下来,让我们编写一个小脚本。

JavaScript (The JavaScript)

In our script we want to control the adding and removing of the opening class and the active class for the trigger button. So, we’ll toggle the classes on click on the trigger button. Additionally, we want to make sure that the scrolling is disabled initially as this would make the content scroll under the intro header. Once we open the content, we allow scrolling. When we load the page, we also want to reset the scroll position so that the content starts at the top.

在我们的脚本中,我们要控制触发按钮的打开类和活动类的添加和删除。 因此,我们将在单击触发按钮时切换类。 另外,我们要确保最初禁用滚动,因为这会使内容在intro标头下滚动。 打开内容后,我们便可以滚动。 加载页面时,我们还想重置滚动位置,以使内容从顶部开始。


<script src="js/classie.js"></script>
<script>
	(function() {

		var container = document.getElementById( 'container' ),
			trigger = container.querySelector( 'button.trigger' );

		function toggleContent() {
			if( classie.has( container, 'container--open' ) ) {
				classie.remove( container, 'container--open' );
				classie.remove( trigger, 'trigger--active' );
				window.addEventListener( 'scroll', noscroll );
			}
			else {
				classie.add( container, 'container--open' );
				classie.add( trigger, 'trigger--active' );
				window.removeEventListener( 'scroll', noscroll );
			}
		}

		function noscroll() {
			window.scrollTo( 0, 0 );
		}

		// reset scrolling position
		document.body.scrollTop = document.documentElement.scrollTop = 0;

		// disable scrolling
		window.addEventListener( 'scroll', noscroll );

		trigger.addEventListener( 'click', toggleContent );

	})();
</script>

And that’s it! We’ve created a simple layout with an interesting effect while playing with some new properties 🙂

就是这样! 我们在使用一些新属性的同时创建了一个具有有趣效果的简单布局new

We really hope you enjoyed this tutorial and find it useful!

我们真的希望您喜欢本教程并发现它有用!

The second demo is an advanced variation, where we have multiple containers and a navigation. Check out the markup and code to see how it was augmented. The containers are moved by adding classes that will trigger CSS animations.

第二个演示是一个高级变体,其中我们有多个容器和一个导航。 查看标记和代码,以了解如何对其进行增强。 通过添加将触发CSS动画的类来移动容器。

If you’d like to learn how to create a website with this layout, check out Velveteen Web Design’s video tutorial on YouTube.

如果您想学习如何使用这种布局创建网站,请查看YouTube上的Velveteen Web Design视频教程

翻译自: https://tympanus.net/codrops/2014/12/23/sliding-header-layout/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值