整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

CSS新特性contain,控制页面的重绘与重排

CSS新特性contain,控制页面的重绘与重排

介绍新的 CSS 属性 contain 之前,读者首先需要了解什么是页面的重绘与重排。

之前已经描述过很多次了,还不太了解的可以先看看这个提高 CSS 动画性能的正确姿势。

OK,下面进入本文正题,

contain 为何?

contain 属性允许我们指定特定的 DOM 元素和它的子元素,让它们能够独立于整个 DOM 树结构之外。目的是能够让浏览器有能力只对部分元素进行重绘、重排,而不必每次都针对整个页面。

The contain property allows an author to indicate that an element and its contents are, as much as possible, independent of the rest of the document tree. This allows the browser to recalculate layout, style, paint, size, or any combination of them for a limited area of the DOM and not the entire page.

contain 语法

看看它的语法:

{
  /* No layout containment. */
  contain: none;
  /* Turn on containment for layout, style, paint, and size. */
  contain: strict;
  /* Turn on containment for layout, style, and paint. */
  contain: content;
  /* Turn on size containment for an element. */
  contain: size;
  /* Turn on layout containment for an element. */
  contain: layout;
  /* Turn on style containment for an element. */
  contain: style;
  /* Turn on paint containment for an element. */
  contain: paint;
}
复制代码

除去 none,取值还有 6 个,我们一个一个来看看。

contain: size

contain: size: 设定了 contain: size 的元素的渲染不会受到其子元素内容的影响。

The value turns on size containment for the element. This ensures that the containing box can be laid out without needing to examine its descendants.

我开始看到这个定义也是一头雾水,光看定义很难明白到底是什么意思。还需实践一番:

假设我们有如下简单结构:

<div class="container">
   
</div>
复制代码
.container {
    width: 300px;
    padding: 10px;
    border: 1px solid red;
}

p {
    border: 1px solid #333;
    margin: 5px;
    font-size: 14px;
}
复制代码

并且,借助 jQuery 实现每次点击容器添加一个 <p>Coco</p> 结构:

$('.container').on('click', e=> {
    $('.container').append('<p>Coco</p>')
})
复制代码

那么会得到如下结果:

可以看到,容器 .container 的高度是会随着元素的增加而增加的,这是正常的现象。

此刻,我们给容器 .container 添加一个 contain: size,也就会出现上述说的:设定了 contain: size 的元素的渲染不会受到其子元素内容的影响

.container {
    width: 300px;
    padding: 10px;
    border: 1px solid red;
+   contain: size
}
复制代码

再看看会发生什么:

正常而言,父元素的高度会因为子元素的增多而被撑高,而现在,子元素的变化不再影响父元素的样式布局,这就是 contain: size 的作用。

contain: style

接下来再说说 contain: style、contain: layout 、contain: paint。先看看 contain: style。

截止至本文书写的过程中,contain: style 暂时被移除了。

CSS Containment Module Level 1: Drop the at-risk “style containment” feature from this specification, move it Level 2。

嗯,官方说辞是因为存在某些风险,暂时被移除,可能在规范的第二版会重新定义吧,那这个属性也暂且放一放。

contain: paint

contain: paint:设定了 contain: paint 的元素即是设定了布局限制,也就是说告知 User Agent,此元素的子元素不会在此元素的边界之外被展示,因此,如果元素不在屏幕上或以其他方式设定为不可见,则还可以保证其后代不可见不被渲染。

This value turns on paint containment for the element. This ensures that the descendants of the containing box don’t display outside its bounds, so if an element is off-screen or otherwise not visible, its descendants are also guaranteed to be not visible.

这个稍微好理解一点,先来看第一个特性:

设定了 contain: paint 的元素的子元素不会在此元素的边界之外被展示

  • 设定了 contain: paint 的元素的子元素不会在此元素的边界之外被展示

这个特点有点类似与 overflow: hidden,也就是明确告知用户代理,子元素的内容不会超出元素的边界,所以超出部分无需渲染。

简单示例,假设元素结构如下:

<div class="container">
    <p>Coco</p>
</div>
复制代码
.container {
    contain: paint;
    border: 1px solid red;
}

p{
    left: -100px;
}
复制代码

我们来看看,设定了 contain: paint 与没设定时会发生什么:

CodePen Demo -- contain: paint Demo

设定了 contain: paint 的元素在屏幕之外时不会渲染绘制

通过使用 contain: paint, 如果元素处于屏幕外,那么用户代理就会忽略渲染这些元素,从而能更快的渲染其它内容。

contain: layout

contain: layout:设定了 contain: layout 的元素即是设定了布局限制,也就是说告知 User Agent,此元素内部的样式变化不会引起元素外部的样式变化,反之亦然。

This value turns on layout containment for the element. This ensures that the containing box is totally opaque for layout purposes; nothing outside can affect its internal layout, and vice versa.

启用 contain: layout 可以潜在地将每一帧需要渲染的元素数量减少到少数,而不是重新渲染整个文档,从而为浏览器节省了大量不必要的工作,并显着提高了性能。

使用 contain:layout,开发人员可以指定对该元素任何后代的任何更改都不会影响任何外部元素的布局,反之亦然。

因此,浏览器仅计算内部元素的位置(如果对其进行了修改),而其余DOM保持不变。因此,这意味着帧渲染管道中的布局过程将加快。

存在的问题

描述很美好,但是在实际 Demo 测试的过程中(截止至2021/04/27,Chrome 90.0.4430.85),仅仅单独使用 contain:layout 并没有验证得到上述那么美好的结果。

设定了 contain: layout 的指定元素,该元素的任何后代的任何更改还是会影响任何外部元素的布局,点击红框会增加一条 <p>Coco<p> 元素插入到 container 中:

简单的代码如下:

<div class="container">
    <p>Coco</p>
    ...
</div>
<div class="g-test"></div>
复制代码
html,
body {
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    gap: 10px;
}

.container {
    width: 150px;
    padding: 10px;
    contain: layout;
    border: 1px solid red;
}

.g-test {
    width: 150px;
    height: 150px;
    border: 1px solid green;
}
复制代码

CodePen Demo -- contain: layout Demo

Can i Use -- CSS Contain

截止至 2021-04-27,Can i Use 上的 CSS Contain 兼容性,已经可以开始使用起来:

参考文献

  • CSS Containment Module Level 1
  • CSS containment
  • CSS Containment in Chrome 52


链接:https://juejin.cn/post/6958990366888607757
来源:掘金

SS的布局有太多种方式,元素的表现也有很多的形式。

像我们熟悉的那些:行内元素、块元素、列表元素、表格元素、绝对定位、固定定位、浮动、弹性布局、网格布局等等等等。

一个元素的具体渲染可能会受到父子元素、兄弟元素的影响。

大多数情况我们都可以通过一些手段,来解决我们遇到的布局或表现问题。

比如给一个元素赋予了浮动,那么可以通过清除浮动来消除影响,再比如通过绝对定位来调整元素的位置,也可以通过padding或margin等避免其他元素被覆盖。

但是也有那么一些情况,我们不太好处理,比如某一个元素希望相对于它的父级区域做固定定位,而不是基于整个页面,能做到吗?再比如给定一个盒容器,无论子元素怎么排序布局或者浮动,也不会影响其他相邻盒子的渲染,该怎么做到?

其实不止这些,还有很多的实际场景让我们很棘手,你是否在设计和实现方面做过平衡和妥协?

对于现在的浏览器来说,所支持的CSS功能不允许我们说:我不行,我做不到。

别的不说,今天要讲的contain就能用来解决上面的问题,它能做的事情还有很多,基于自身天然的属性,甚至能轻松提升你的性能!

contain概述

contain表明该元素要独立于页面中的其他元素,该元素中的所有内容都被局限在一个独立的区域,跟其他元素隔离开来,从而使得基于该元素的所有计算都是独立的,被限制在该DOM子树中,而不是整个页面。这样能够让页面的性能提升。

该元素构成的容器,可以控制其产生的尺寸范围、样式作用域、布局方式、绘制区域。会生成新的包含区块、新的层叠上下文、新的区块格式化上下文。这些控制手段都对应着不同的局限属性,在容器内对局限属性的修改,不会影响容器外的部分,也就不会使得页面经常重新渲染,尤其在动态修改页面元素时会带来更好的性能受益。

我们理解它的时候,不要把它想成是包含的意思,理解成它的作用,是对包含内容的一个局限,之后也会多次用到"局限"这个词。

分类

一、关键词

通过关键词,可以指定不同的局限属性,从而产生不同的局限效果。

  1. none:不应用任何局限。
  2. size:元素的尺寸无视子元素而单独计算,在行向和块向上都应用该局限。
  3. inline-size:元素的尺寸无视子元素而单独计算,只在行向上应用该局限。
  4. layout:使得该元素的布局与元素外的任何内容相互独立,互不影响。即该元素所构成的容器从页面中隔离出来,单独计算布局。
  5. style:对于容器内的某些可能影响外部属性的值,被限制在容器内,不参与整体的计算,比如计数器和引号不会参与之前或者之后的计算,会有独立的计算,对于外面来说就好像这个元素没存在过一样,或者说不知道有它的存在。
  6. paint:限制该元素的绘制区域范围,子元素的渲染永远不会出现在容器外,容器的边界限定了子元素的可见内容。例如容器在屏幕外,那么就永远不用绘制,因为其子元素也肯定在屏幕外,不像margin负值放在屏幕外那样,子元素可能延伸到屏幕内。
  7. content:相当于设置了layout、paint、style,也就是除了size之外的所有值。
  8. strict:给该元素应用所有局限规则,相当于设置size、layout、paint、style。

二、组合值

也就是上面2-6关键字的任意组合,跟顺序无关,多个值之间用空格分隔开。跟个数也无关,可以设置任意的数量。不过要注意,size和inline-size同时只能设置一个,因为它俩是冲突的。

三、全局值

全局值的作用,可以参考我在font-size那篇文章中的解释说明,它们的作用机制和原理都是一样的,这里不在重复赘述。

示例

我们来对上面所说的内容,做一些示例,来看看它们的实际工作方式。

先构建一个基本的代码,之后都以这个为基础改造和演示:

<div style="background-color: bisque;">
  我是父元素
  <div style="background-color: coral;">
    我是子元素
  </div>
</div>
<div style="background-color: lightpink;">
  我是父兄弟元素
</div>

看下现在的效果:

效果

记住这个效果,因为我们接下来就要改变contain属性,观察它所发生的变化。

  1. 通过尺寸来控制
<div style="contain: size;background-color: bisque;">
  我是父元素
  <div style="background-color: coral;">
    我是子元素
  </div>
</div>
<div style="background-color: lightpink;">
  我是父兄弟元素
</div>

给父元素加上contain:size样式:

效果

可以看到,"我是父元素"和"我是父兄弟元素"重合了,也就说,父兄弟元素的渲染,直接从父元素渲染开始的位置开始渲染的。就好像父元素不存在一样。

这里面的奥妙通过控制台看一下,其实就很容易解开了:

效果

就是因为父元素的高度为0了。在解释之前先说明一下,行向指的是我们书写的方向,就是指的从左往右,你就可以理解成是多个行内元素排列的方向,一直往后面追加的方向。块向指的是我们折行的方向,也就是指的从上往下,你就可以理解成是多个块级元素排列的方向,一直往下追加的方向。

理解了这两个之后,我们就知道,由于size影响着这两个方向上的局限,它会变得无视子元素。因为如果没有主动设置尺寸的话,就好像子元素不存在一样,那么它就没有高度,所以兄弟元素就自然而然的顶上来了。

这时,我们改一下设置,让它只在行向上有局限:

<div style="contain: inline-size;background-color: bisque;">
  我是父元素
  <div style="background-color: coral;">
    我是子元素
  </div>
</div>
<div style="background-color: lightpink;">
  我是父兄弟元素
</div>

通过设置contain:inline-size:

效果

可以看到,效果又回来了,这是因为我们没有在块向上做局限,因此高度会自然撑开。

既然说到了这里,我们再看一下,它是如何在行向上进行局限的,构造如下代码:

<div style="contain: inline-size;display: inline-block;background-color: bisque;">
  我是父元素
  <div style="background-color: coral;">
    我是子元素
  </div>
</div>
<div style="background-color: lightpink;">
  我是父兄弟元素
</div>

设置父元素为行内块,增加display:inline-block:

效果

瞬间又变成了这样,这同样是因为,行内局限使得父元素独立计算尺寸,而我们又没手动指定,因此它的宽度为0,子元素也跟着宽度为0,所以就变成了一个字一换行。

这时即使你给子元素加上宽度,在行向上父元素也会无视你:

效果

你看我们给子元素加上100px的宽度,但是鼠标查看父元素,依然是宽度为0。

  1. 通过布局来控制

指定contain:layout,可以让该元素独立计算它的内部布局,不受外界影响,我们先将子元素设定一个固定定位:

<div style="background-color: bisque;">
  我是父元素
  <div style="position: fixed;top: 10px;background-color: coral;">
    我是子元素
  </div>
</div>
<div style="background-color: lightpink;">
  我是父兄弟元素
</div>

看下现在的效果:

效果

完全没毛病,子元素固定到页面顶部的10px位置。

现在应用一下我们的布局限制:

<div style="contain: layout;background-color: bisque;">
  我是父元素
  <div style="position: fixed;top: 10px;background-color: coral;">
    我是子元素
  </div>
</div>
<div style="background-color: lightpink;">
  我是父兄弟元素
</div>

再看下显示的效果:

效果

咦?明明是固定定位,它的位置却是相对于父元素的。这就是布局限制的作用,相当于父元素告诉页面,从现在开始,这片的布局归我管,所有的行为都向我请示,由我指挥。

同样,其他的position值,也都是基于父元素的布局限制来渲染的,这里就不做一一演示了。

其实,不光是position,只要是关于布局的,都会在此局限下生效,这里再演示一个浮动的例子:

<div style="height: 80px;padding: 5px;background-color: bisque;">
  <h2 style="margin-bottom: 7px;">我是父元素</h2>
  <p style="float: left;background-color: coral;">
    我是子元素
  </p>
</div>
<div style="height: 80px;padding: 5px;background-color: lightpink;">
  <h2>我是父兄弟元素</h2>
  <p style="background-color: coral;">
    我是父兄弟子元素
  </p>
</div>

两个父元素各包含两个子元素,其中第一个父元素的第二个子元素设置为左浮动,为了更好的演示,我把子元素改成了h2和p标签,看下现在的效果:

效果

父元素的两个子元素正常显示,但是父兄弟元素的第一个子元素里面的文字,被挤的偏移了,这是由于父元素的第二个子元素设置浮动引起的,通过控制台看下就明白了:

效果

红线是我标出来的,可以看到,父兄弟元素的h2和父元素的浮动有一丁点的重合,导致文字被推开,这就是浮动产生的影响。

我们通过布局局限,来控制浮动只发生在局限内,稍微改下代码:

<div style="contain: layout;height: 80px;padding: 5px;background-color: bisque;">
  <h2 style="margin-bottom: 7px;">我是父元素</h2>
  <p style="float: left;background-color: coral;">
    我是子元素
  </p>
</div>
<div style="height: 80px;padding: 5px;background-color: lightpink;">
  <h2>我是父兄弟元素</h2>
  <p style="background-color: coral;">
    我是父兄弟子元素
  </p>
</div>

给父元素添加了contain:layout,这是浮动就不会影响后面的布局了:

效果

通过布局局限,我们可以把所有的关于布局的影响,都控制在容器内,这样即使容器内布局发生了改变,也完全不会影响页面其他内容,在动态页面中,如果需要频繁的修改某些元素,通过这种方式管理和设计页面,就能很有效的改善渲染的性能。

  1. 通过样式来控制

这里的样式主要是针对计数器和引号的作用域,能控制它们只在所局限的范围内单独计算,而不会影响全局的结果,就好像它们是单独拿出来作为一个独立的文档一样,看个例子:

body {
  counter-reset: my-list;
}
div > div::before {
  counter-increment: my-list;
  content: "(" counter(my-list) "):";
}
<div>
  <div>第1行</div>
  <div>第2行</div>
  <div>第3行</div>
  <div>第4行</div>
  <div>第5行</div>
  <div>第6行</div>
</div>

我们设计这样一个列表,通过自定义的计数器,设置一个前缀的显示:

效果

如果我们希望第三行独立出来,进行样式局限,不参与外部计数:

<div>
  <div>第1行</div>
  <div>第2行</div>
  <div style="contain: style;">第3行</div>
  <div>第4行</div>
  <div>第5行</div>
  <div>第6行</div>
</div>

那么它就会展现成这个样子:

效果

注意第三行的计数,已经重置为1,并且第四行从3开始,接着第二行的值继续计数。

  1. 通过绘制来控制

这个也比较厉害,就是父元素啥样就是啥样,子元素永远不会在容器外渲染:

<div style="background-color: bisque;width: 100px;height: 100px;">
  <div>
  海客谈瀛洲,烟涛微茫信难求。
  越人语天姥,云霞明灭或可睹。
  天姥连天向天横,势拔五岳掩赤城。
    </div>
</div>

有这样一个代码块,容器的宽高为100px,内容有超出部分:

效果

我们可以通过绘制局限来使容器外的内容不显示:

<div style="contain: style;background-color: bisque;width: 100px;height: 100px;">
  <div>
  海客谈瀛洲,烟涛微茫信难求。
  越人语天姥,云霞明灭或可睹。
  天姥连天向天横,势拔五岳掩赤城。
  </div>
</div>

添加contain:paint,只让绘制区域被限制在容器内部:

效果

这个跟overflow:hidden有一点区别,就是绘制局限真的就是正常绘制,只不过不绘制容器外的部分,而hidden虽然隐藏,但是依然能通过js进行滚动。

  1. 通过组合值来控制

我们也可以通过任意的值的组合来控制所需要的局限,也可以通过strict或content关键字来快速的做到这一点。这里就不再重复演示了

最后

合理的使用contain,不但能快速实现我们的需求,也能减少我们的修改量,而且会降低不理解现象的情况的出现频率,更能提升页面的性能。

尤其是布局局限,提供给了我们更多的发挥空间,而且任意的复制到其他地方,也不会对外部元素有影响。

每天一点小知识,希望能够帮助到你。

hat about covers the basics of the mail function; now let’s really get fancy and explore mail headers and what we can do with them!

上篇文章涵盖了邮件功能的基本知识;现在,让我们真正开始想象和探索邮件标题以及我们可以用它们做什么!

HTML Email and Other Headers

HTML电子邮件和其他头信息

So now you can send email from your PHP scripts. How exciting! Although I’m sure you’re already drunk with power, would you like to know how to send HTML email too? Of course you would!

现在您可以从PHP脚本发送电子邮件了。多么令人兴奋!虽然我肯定你已经被权力迷住了,但你想知道如何发送HTML电子邮件吗?你当然会!

To understand HTML email, first you need to understand mail headers. Any given email message is made up of two parts: the headers and the message body. Here’s how a simple message looks when your email program fetches it from your ISP:

要理解HTML电子邮件,首先需要理解邮件头信息。任何给定的电子邮件都由两部分组成:头信息和邮件正文。下面是当您的电子邮件程序从ISP获取简单邮件时的展现:

Return-Path: <sender@elsewhere.com>
Delivered-To: you@some.net
Received: ...several lines like this...
From: Sender <sender@elsewhere.com>
To: You <you@some.net>
Subject: A Simple Message
Date: Mon, 11 Feb 2002 16:08:19 -0500
Organization: Sender's Company
X-Mailer: Microsoft Outlook, Build 10.0.2616
Hi there! <tap> <tap> Is this thing on?

Everything up to the blank line makes up the headers for this message. In actual fact, most email messages will have many more header lines than this; however, to keep our focus I trimmed this example down to the bare essentials.

到空白行的所有内容构成了该消息的标头。实际上,大多数电子邮件的头信息都比这多很多;然而,为了保持我们的关注点,我把这个例子缩减到了最基本的部分。

As you can see, every line of the headers begins with the name of the header (From:, To:, Subject:, Date:, etc.), followed by some value. Most headers are standardized, and have a specific meaning, either to your mail program or to the mail servers that were responsible for getting the message to you. Non-standard headers exist as well, and they all begin with X- (e.g. X-Mailer:, a non-standard header, often appears to indicate the program that was used to send the message).

如您所见,标题的每一行都以标题的名称(From:、To:、Subject:、Date:,等等)开头,后跟一些值。大多数邮件头都是标准化的,对您的邮件程序或负责向您发送邮件的邮件服务器都有特定的含义。非标准标头也存在,它们都以X开头(例如,X-Mailer:,一个非标准标头,通常显示为指示用于发送消息的程序)。

NOTE: If a header’s value needs more than one line, additional lines should begin with a space. We’ll see an example of this in the next section.

如果标头的值需要多行,则其他行应以空格开头。我们将在下一节中看到一个例子。

As soon as your mail program gets to a blank line, it knows the headers are over and the rest of the email is the message body, which it should display. In this case, the message body is the last line above.

一旦你的邮件程序到达一个空行,它就知道邮件头已经结束,邮件的其余部分就是邮件正文,应该显示出来。在本例中,消息正文是上面的最后一行。

PHP’s mail function lets you specify your own headers, which it adds to those it generates automatically to get your message where it needs to go. For example, the following call to the mail function will add an X-Mailer: header to the outgoing message, identifying PHP 4.x as the sending program:

PHP的邮件功能允许您指定自己的邮件头,并将其添加到自动生成的邮件头中,以便将邮件发送到需要的地方。例如,以下对mail函数的调用将向传出消息添加一个X-Mailer:header,将PHP 4.X标识为发送程序:

<?php
mail('recipient@some.net', 'Subject', 'Your message here.',
'X-Mailer: PHP 4.x');
?>

This optional fourth parameter is most often used to specify a ‘from’ address other than the default specified in php.ini. Let’s add a From: header to do just that:

这个可选的第四个参数最常用于指定“from”地址,而不是php.ini中指定的默认地址。让我们添加一个From:header来实现这一点:

<?php
mail('recipient@some.net', 'Subject', 'Your message here.',
"From: sender@some.netnX-Mailer: PHP 4.x");
?>

Note that since headers each appear on a single line, we must separate our two headers with a new line character (n), which means I need to use double quotes around the header string (single quoted strings don’t recognize special character codes like n).

请注意,由于每个标题都显示在一行上,因此我们必须用新行字符(n)分隔两个标题,这意味着我需要在标题字符串周围使用双引号(单引号字符串不能识别像n这样的特殊字符代码)。

Additional headers also let you assign names to email addresses by specifying them in the format name <email>. Here’s our example again, but this time with names “The Sender” and “The Receiver” attached to the relevant addresses:

其他标题还允许您通过在格式名称<email>中指定电子邮件地址来为其分配名称。下面是我们的示例,但这一次在相关地址上附加了名称“发件人”和“收件人”:

<?php
mail('recipient@some.net', 'Subject', 'Your message here.',
"To: The Receiver <recipient@some.net>n" .
"From: The Sender <sender@some.net>n" .
"X-Mailer: PHP 4.x");
?>

Notice that to do this, we’ve had to specify the To: header manually, since the first parameter of PHP’s mail function doesn’t support this more advanced address format. We must still list all the recipients of the message as bare email addresses in the first parameter, however.

注意,要做到这一点,我们必须手动指定to:头,因为PHP邮件函数的第一个参数不支持这种更高级的地址格式。但是,我们仍然必须在第一个参数中将邮件的所有收件人列为裸电子邮件地址。

The cc: and Bcc: headers provide the ability to send carbon copies and blind carbon copies of a message as well:

cc:和Bcc:标头还提供发送邮件的复写副本和盲复写副本的功能:

<?php
mail('recipient@some.net, someone@some.net, metoo@some.net',
'Subject', 'Your message here.',
"To: The Receiver <recipient@some.net>n" .
"From: The Sender <sender@some.net>n" .
"cc: Interested <someone@some.net>n" .
"Bcc: Me Too <metoo@some.net>n" .
"X-Mailer: PHP 4.x");
?>

See how the email addresses of all recipients, be they actual addressees (To), carbon copies (Cc), or blind carbon copies (Bcc) are listed in the first parameter? This isn’t documented anywhere, but in my testing I’ve found that it’s absolutely vital if you want the message to get to everyone it’s supposed to, especially on Windows servers where PHP’s mail function is especially sensitive.

查看如何在第一个参数中列出所有收件人的电子邮件地址,无论是实际收件人(收件人)、复写副本(抄送)还是盲复写副本(密件抄送)?这在任何地方都没有文档记录,但在我的测试中,我发现,如果希望消息传递给所有人,尤其是在PHP邮件功能特别敏感的Windows服务器上,这是绝对重要的。

What does all this have to do with HTML email, you ask? Well, a few special headers will cause the message body to be interpreted as HTML by email clients that support it:

你会问,这一切与HTML电子邮件有什么关系?好的,一些特殊的标题将导致支持邮件正文的电子邮件客户端将邮件正文解释为HTML:

<?php
mail('recipient@some.net', 'Subject',
'<html><body><p>Your <i>message</i> here.</p></body></html>',
"To: The Receiver <recipient@some.net>n" .
"From: The Sender <sender@some.net>n" .
"MIME-Version: 1.0n" .
"Content-type: text/html; charset=iso-8859-1");
?>

Note both the message in HTML format as well as the two new headers: Mime-Version: and Content-type:.

请注意HTML格式的消息以及两个新标头:Mime-Version:和Content-type:。

The MIME-Version: header indicates that the standard extended mail format will be used (MIME stands for Multipurpose Internet Mail Extensions), which allows for messages to be sent content types other than plain text. The Content-type: header then specifies that the message with contain HTML (and sets the character set to the standard for that format).

MIME-Version:标头表示将使用标准的扩展邮件格式(MIME代表多用途Internet邮件扩展),它允许发送除纯文本以外的内容类型的邮件。然后,Content-type:头指定消息包含HTML(并将字符集设置为该格式的标准)。