创建精美的盒子

CSS 框是任何使用 CSS 设计的网页的构建块。让它们看起来漂亮既有趣又具有挑战性。这很有趣,因为这一切都是为了将设计理念转化为工作代码;由于 CSS 的限制,这很有挑战性。让我们做一些别致的盒子。

¥CSS boxes are the building blocks of any web page styled with CSS. Making them nice looking is both fun and challenging. It's fun because it's all about turning a design idea into working code; it's challenging because of the constraints of CSS. Let's do some fancy boxes.

在我们开始实际操作之前,请确保你熟悉 CSS 盒子模型。熟悉一些 CSS 布局基础知识 也是一个好主意,但不是先决条件。

¥Before we start getting into the practical side of it, make sure you are familiar with the CSS box model. It's also a good idea, but not a prerequisite, to be familiar with some CSS layout basics.

在技术方面,创建精美的盒子就是掌握 CSS 边框和背景属性以及如何将它们应用到给定的盒子。但除了技术之外,还在于释放你的创造力。这不是一天就能完成的,一些 Web 开发者一生都在享受它。

¥On the technical side, Creating fancy boxes are all about mastering CSS border and background properties and how to apply them to a given box. But beyond the techniques it's also all about unleashing your creativity. It will not be done in one day, and some web developers spend their whole life having fun with it.

我们将看到很多示例,但我们将始终致力于最简单的 HTML 片段,即一个简单的元素:

¥We are about to see many examples, but we will always work on the most simple piece of HTML possible, a simple element:

html
<div class="fancy">Hi! I want to be fancy.</div>

好的,这只是一小段 HTML,我们可以对该元素进行哪些调整?所有以下内容:

¥Ok, that's a very small bit of HTML, what can we tweak on that element? All the following:

所以我们有一个非常大的操场。让乐趣开始。

¥So we have a very large playground. Let the fun begin.

盒子模型调整

¥Box model tweak

仅盒子模型就可以让我们做一些基本的事情,例如添加简单的边框、制作正方形等。当你通过使 border-radius 大于 padding 和/或 - margin 将属性推向极限时,它开始变得有趣 盒子的实际尺寸。

¥The box model alone allows us to do some basic stuff, like adding simple borders, making squares, etc. It starts to get interesting when you push the properties to the limit by having negative padding and/or- margin by having border-radius larger than the actual size of the box.

画圈

¥Making circles

html
<div class="fancy">Hi! I want to be fancy.</div>

这是一件非常简单又非常有趣的事情。border-radius 属性用于创建应用于框的圆角,但如果半径大小等于或大于框的实际宽度会发生什么情况?

¥This is something that is both very simple and very fun. The border-radius property is made to create a rounded corner applied to boxes, but what happens if the radius size is equal or larger than the actual width of the box?

css
.fancy {
  /* Within a circle, centered text looks prettier. */
  text-align: center;

  /* Let's avoid our text touching the border. As
     our text will still flow in a square, it looks
     nicer that way, giving the feeling that it's a "real"
     circle. */
  padding: 1em;

  /* The border will make the circle visible.
     You could also use a background, as
     backgrounds are clipped by border radius */
  border: 0.5em solid black;

  /* Let's make sure we have a square.
     If it's not a square, we'll get an
     ellipsis rather than a circle */
  width: 4em;
  height: 4em;

  /* and let's turn the square into a circle */
  border-radius: 100%;
}

是的,我们得到一个圆圈:

¥Yes, we get a circle:

背景

¥Backgrounds

当我们谈论一个精美的盒子时,处理它的核心属性是 背景-* 属性。当你开始摆弄背景时,就像你的 CSS 框变成了需要填充的空白画布。

¥When we talk about a fancy box, the core properties to handle that are background-* properties. When you start fiddling with backgrounds it's like your CSS box is turned into a blank canvas you'll fill.

在我们开始讨论一些实际示例之前,让我们退后一步,因为你应该了解有关背景的两件事。

¥Before we jump to some practical examples, let's step back a bit as there are two things you should know about backgrounds.

  • 可以在单个盒子上设置 几个背景。它们像层一样堆叠在一起。
  • 背景可以是纯色或图片:纯色始终填充整个表面,但图片可以缩放和定位。
html
<div class="fancy">Hi! I want to be fancy.</div>

好吧,让我们享受背景的乐趣:

¥Okay, let's have fun with backgrounds:

css
.fancy {
  padding: 1em;
  width: 100%;
  height: 200px;
  box-sizing: border-box;

  /* At the bottom of our background stack,
     let's have a misty grey solid color */
  background-color: #e4e4d9;

  /* We stack linear gradients on top of each
     other to create our color strip effect.
     As you will notice, color gradients are
     considered to be images and can be
     manipulated as such */
  background-image: linear-gradient(175deg, rgb(0 0 0 / 0%) 95%, #8da389 95%),
                    linear-gradient( 85deg, rgb(0 0 0 / 0%) 95%, #8da389 95%),
                    linear-gradient(175deg, rgb(0 0 0 / 0%) 90%, #b4b07f 90%),
                    linear-gradient( 85deg, rgb(0 0 0 / 0%) 92%, #b4b07f 92%),
                    linear-gradient(175deg, rgb(0 0 0 / 0%) 85%, #c5a68e 85%),
                    linear-gradient( 85deg, rgb(0 0 0 / 0%) 89%, #c5a68e 89%),
                    linear-gradient(175deg, rgb(0 0 0 / 0%) 80%, #ba9499 80%),
                    linear-gradient( 85deg, rgb(0 0 0 / 0%) 86%, #ba9499 86%),
                    linear-gradient(175deg, rgb(0 0 0 / 0%) 75%, #9f8fa4 75%),
                    linear-gradient( 85deg, rgb(0 0 0 / 0%) 83%, #9f8fa4 83%),
                    linear-gradient(175deg, rgb(0 0 0 / 0%) 70%, #74a6ae 70%),
                    linear-gradient( 85deg, rgb(0 0 0 / 0%) 80%, #74a6ae 80%);
}

注意:渐变可以以一些非常有创意的方式使用。如果你想看一些有创意的例子,可以看看 Lea Verou 的 CSS 模式。如果你想了解有关渐变的更多信息,请随时进入 我们的专门文章

¥Note: Gradients can be used in some very creative ways. If you want to see some creative examples, take a look at Lea Verou's CSS patterns. If you want to learn more about gradients, feel free to get into our dedicated article.

伪元素

¥Pseudo-elements

当设计单个盒子时,你可能会发现自己受到限制,并且可能希望拥有更多盒子来创造更令人惊叹的风格。大多数时候,为了样式的独特目的而添加额外的 HTML 元素会导致污染 DOM。即使有必要,这也被认为是不好的做法。避免此类陷阱的一种解决方案是使用 CSS 伪元素

¥When styling a single box, you could find yourself limited and could wish to have more boxes to create even more amazing styles. Most of the time, that leads to polluting the DOM by adding extra HTML element for the unique purpose of style. Even if it is necessary, it's somewhat considered bad practice. One solution to avoid such pitfalls is to use CSS pseudo-elements.

一朵云

¥A cloud

html
<div class="fancy">Hi! I want to be fancy.</div>

让我们举个例子,将盒子变成云:

¥Let's have an example by turning our box into a cloud:

css
.fancy {
  text-align: center;

  /* Same trick as previously used to make circles */
  box-sizing: border-box;
  width: 150px;
  height: 150px;
  padding: 80px 1em 0 1em;

  /* We make room for the "ears" of our cloud */
  margin: 0 100px;

  position: relative;

  background-color: #a4c9cf;

  /* Well, actually we are not making a full circle
     as we want the bottom of our cloud to be flat.
     Feel free to tweak this example to make a cloud
     that isn't flat at the bottom ;) */
  border-radius: 100% 100% 0 0;
}

/* Those are common style that apply to both our ::before
   and ::after pseudo elements. */
.fancy::before,
.fancy::after {
  /* This is required to be allowed to display the
     pseudo-elements, event if the value is an empty
     string */
  content: "";

  /* We position our pseudo-elements on the left and
     right sides of the box, but always at the bottom */
  position: absolute;
  bottom: 0;

  /* This makes sure our pseudo-elements will be below
     the box content whatever happens. */
  z-index: -1;

  background-color: #a4c9cf;
  border-radius: 100%;
}

.fancy::before {
  /* This is the size of the clouds left ear */
  width: 125px;
  height: 125px;

  /* We slightly move it to the left */
  left: -80px;

  /* To make sure that the bottom of the cloud
     remains flat, we must make the bottom right
     corner of the left ear square. */
  border-bottom-right-radius: 0;
}

.fancy::after {
  /* This is the size of the clouds left ear */
  width: 100px;
  height: 100px;

  /* We slightly move it to the right */
  right: -60px;

  /* To make sure that the bottom of the cloud
     remains flat, we must make the bottom left
     corner of the right ear square. */
  border-bottom-left-radius: 0;
}

块引用

¥Blockquote

使用伪元素的一个更实际的示例是为 HTML <blockquote> 元素构建良好的格式。让我们看一个 HTML 片段略有不同的示例(这为我们提供了了解如何处理设计本地化的机会):

¥A more practical example of using pseudo-elements is to build a nice formatting for HTML <blockquote> elements. So let's see an example with a slightly different HTML snippet (which provide us an opportunity to see how to also handle design localization):

html
<blockquote>
  People who think they know everything are a great annoyance to those of us who
  do. <i>Isaac Asimov</i>
</blockquote>
<blockquote lang="fr">
  L'intelligence, c'est comme les parachutes, quand on n'en a pas, on s'écrase.
  <i>Pierre Desproges</i>
</blockquote>

所以我们的风格是这样的:

¥So here comes our style:

css
blockquote {
  min-height: 5em;
  padding: 1em 4em;
  font: 1em/150% sans-serif;
  position: relative;
  background-color: lightgoldenrodyellow;
}

blockquote::before,
blockquote::after {
  position: absolute;
  height: 3rem;
  font:
    6rem/100% Georgia,
    "Times New Roman",
    Times,
    serif;
}

blockquote::before {
  content: "“";
  top: 0.3rem;
  left: 0.9rem;
}

blockquote::after {
  content: "”";
  bottom: 0.3rem;
  right: 0.8rem;
}

blockquote:lang(fr)::before {
  content: "«";
  top: -1.5rem;
  left: 0.5rem;
}

blockquote:lang(fr)::after {
  content: "»";
  bottom: 2.6rem;
  right: 0.5rem;
}

blockquote i {
  display: block;
  font-size: 0.8em;
  margin-top: 1rem;
  text-align: right;
}

全部在一起以及更多

¥All together and more

因此,当我们将所有这些混合在一起时,就有可能创造出美妙的效果。在某种程度上,完成这样的盒子装饰是一个创造力的问题,无论是在设计上还是在 CSS 属性的技术使用上。通过这样做,可以创建视错觉,让你的盒子变得生动起来,就像这个例子一样:

¥So it's possible to create a wonderful effect when we mix all of this together. At some point, to accomplish such box embellishment is a matter of creativity, both in design and technical use of CSS properties. By doing such it's possible to create optical illusions that can bring your boxes alive like in this example:

html
<div class="fancy">Hi! I want to be fancy.</div>

让我们创建一些部分阴影效果。box-shadow 属性允许我们创建内部光和平坦的阴影效果,但通过一些额外的工作,可以通过使用伪元素和 rotate 属性(三个单独的 transform 属性之一)创建更自然的几何体。

¥Let's create some partial drop-shadow effects. The box-shadow property allow us to create inner light and a flat drop shadow effect, but with some little extra work it becomes possible to create a more natural geometry by using a pseudo-element and the rotate property, one of the three individual transform properties.

css
.fancy {
  position: relative;
  background-color: #ffc;
  padding: 2rem;
  text-align: center;
  max-width: 200px;
}

.fancy::before {
  content: "";

  position: absolute;
  z-index: -1;
  bottom: 15px;
  right: 5px;
  width: 50%;
  top: 80%;
  max-width: 200px;

  box-shadow: 0px 13px 10px black;
  rotate: 4deg;
}