创建 CSS 窗帘打开效果

Avatar of Geoff Graham
Geoff Graham

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 价值 200 美元的免费积分!

如果你和我一样老,你可能还记得在老式电视上观看《让我们做一笔交易》。这档节目现在似乎已经以新的形式继续播出,但最初的版本总是因为一件简单的事情而让我印象深刻:揭晓。

不知道窗帘后面是什么,这本身就令人兴奋,这也是《让我们做一笔交易》的全部意义所在。参赛者可以选择三扇门,任何一扇门打开后都会露出奖品。

太刺激了!

这种窗帘滑开,露出宝藏(即使是 Bob's Big Boy 礼品券)的技术,是一个很巧妙的小技巧,我们可以通过一些 CSS 代码来实现它。这是最终的演示

查看 CodePen 上 Geoff Graham (@geoffgraham) 的示例 OXJMmY

HTML 代码

这基本上可以归结为三个元素

  • 窗帘包装器
  • 左侧窗帘面板
  • 右侧窗帘面板

我们可以通过图表来可视化我们正在做的事情

…当窗帘面板滑开时,它们将露出奖品作为第四个元素

让我们用它作为我们 HTML 代码的蓝图。

<!-- The parent component -->
<div class="curtain">
	
  <!-- The component wrapper -->
  <div class="curtain__wrapper">
    
    <!-- The left curtain panel -->
    <div class="curtain__panel curtain__panel--left">

    </div> <!-- curtain__panel -->
    
    <!-- The prize behind the curtain panels -->
    <div class="curtain__prize">

    </div> <!-- curtain__prize -->
    
    <!-- The right curtain panel -->
    <div class="curtain__panel curtain__panel--right">
	    
    </div> <!-- curtain__panel -->
    
  </div> <!-- curtain__wrapper -->

</div> <!-- curtain -->

CSS 布局

现在我们已经在 HTML 代码中定义了元素,我们可以开始使用 CSS 来定位它们。

我们的第一个目标是定位窗帘面板,使其不仅并排排列,而且还在奖品本身的前面。

.curtain {
  width: 100%; /* Ensures the component is the full screen width */
  height: 100vh; /* We're using this for demo purposes */
  overflow: hidden; /* Allows us to slide the panels outside the container without them showing */
}
  
.curtain__wrapper {
  width: 100%;
  height: 100%;
}
      
.curtain__panel {
  background: orange;
  width: 50%; /* Each panel takes up half the container */
  height: 100vh; /* Used for demo purposes */
  float: left; /* Makes sure panels are side-by-side */
  position: relative; /* Needed to define the z-index */
  z-index: 2; /* Places the panels in front of the prize */
}

.curtain__panel--left {
  /* Styles for sliding the left panel */
}

.curtain__panel--right {
  /* Styles for sliding the right panel */
}
  
.curtain__prize {
  background: #333;
  position: absolute; /* Forces the prize position into the container start */
  z-index: 1; /* Places the prize behind the panels, which are z-index 2 */
  width: 100%;
  height: 100%;
}

如果我们现在就停止并检查我们的工作,看起来我们似乎什么都没做。实际上,我们只是看到了一个橙色的块。

查看 CodePen 上 Geoff Graham (@geoffgraham) 的示例 wWvJaO

这是好事!我们实际上是在看两个窗帘面板占据了整个窗帘容器,而奖品面板则隐藏在幕后。

复选框技巧

我不能不提我们要在这里实践复选框技巧。如果你不熟悉复选框技巧,它是一种方法,我们可以根据一个简单表单复选框的已知状态来改变元素的呈现方式。如果你想更深入地了解其工作原理,我们可以 查看有关该方法的文章

使用复选框技巧的第一条规则是,我们必须在标记中添加一个复选框。让我们把它添加到 HTML 代码中

<!-- The parent component -->
<div class="curtain">
	
  <!-- The component wrapper -->
  <div class="curtain__wrapper">
    
    <!-- The checkbox hack! -->
    <input type="checkbox" checked>
    
    <!-- The left curtain panel -->
    <div class="curtain__panel curtain__panel--left">

    </div> <!-- curtain__panel -->
    
    <!-- The prize behind the curtain panels -->
    <div class="curtain__prize">

    </div> <!-- curtain__prize -->
    
    <!-- The right curtain panel -->
    <div class="curtain__panel curtain__panel--right">
	    
    </div> <!-- curtain__panel -->
    
  </div> <!-- curtain__wrapper -->

</div> <!-- curtain -->

首先,让我们确保我们的复选框既不可见,又占据了整个窗帘组件的空间。我们希望整个窗帘都是可点击的,这将使我们能够做到这一点。

input[type=checkbox] {
  position: absolute; /* Force the checkbox at the start of the container */
  cursor: pointer; /* Indicate the curtain is clickable */
  width: 100%; /* The checkbox is as wide as the component */
  height: 100%; /* The checkbox is as tall as the component */
  z-index: 100; /* Make sure the checkbox is on top of everything else */
  opacity: 0; /* Hide the checkbox */
}

注意,复选框在我们的 HTML 代码中的默认状态是 checked。这使我们能够根据 :checked 状态 来设置元素的样式。

/* When the checkbox is checked... */
        
/* Slide the first panel in */
input[type=checkbox]:checked ~ div.curtain__panel--left {
  transform: translateX(0);
}
        
/* Slide the second panel in */
input[type=checkbox]:checked ~ div.curtain__panel--right {
  transform: translateX(0);
}

这也意味着我们可以更新我们的窗帘面板,使它们在复选框未选中时从容器中滑出。

/* Slide the panel to the left out of the container */
.curtain__panel--left {
  transform: translateX(-100%);
}

/* Slide the panel to the right out of the container */
.curtain__panel--right {
  transform: translateX(100%);
}

现在我们有了进展!点击窗帘组件会将面板移出屏幕,并露出奖品面板。

查看 CodePen 上 Geoff Graham (@geoffgraham) 的示例 xOxqOL

动画化更改

接下来,我们需要在复选框的状态在点击后发生更改时动画化面板的过渡。否则,你可能已经注意到,更改看起来不像滑动门,更像是眨眼。

让我们在 .curtain__panel 类中添加一个 transition

.curtain__panel {
  background: orange;
  width: 50%; /* Each panel takes up half the container */
  height: 100vh; /* Used for demo purposes */
  float: left; /* Makes sure panels are side-by-side */
  position: relative; /* Needed to define the z-index */
  z-index: 2; /* Places the panels in front of the prize */
  transition: all 1s ease-out; /* Animates the sliding transition */
}

我们太酷了!

查看 CodePen 上 Geoff Graham (@geoffgraham) 的示例 aZbJBw

将所有部分整合在一起

现在我们已经将所有工作元素都放在了适当的位置,我们可以开始进行微调,向窗帘面板和奖品面板添加内容。

查看 CodePen 上 Geoff Graham (@geoffgraham) 的示例 OXJMmY