关于 background-position 你需要知道的一切

2025-06-07

关于 background-position 你需要知道的一切

将我的 Stack Overflow 答案之一转换为帖子

目录


我们在处理时background-position有两种常见的情况:

  1. 我们使用像素值(简单的值)
  2. 我们使用百分比值(比较棘手)

让我们开始彻底解释并消除周围的所有歧义background-position

像素值

使用像素值时,无论图像大小如何,参考点都是图像的左上角。这就像在定位元素中使用左上角一样:

请注意,其他单位(例如emch等)的行为与 相同px。它们被称为长度。我们的比较可以推广到长度百分比。您只需知道如何将每个长度转换为像素即可。

百分比值

使用百分比值时,参考与使用像素值时不同;它不再是上角/左角:

在这种情况下,我们需要考虑两个参数:容器的大小和图像的大小。以下是其工作原理的说明(我取了background-position等于30% 30%):

百分比

首先,我们考虑图像,找到用于放置图像的参考点。它是图像内部的点,根据图像的大小,30% 30%从左上角算起如绿线所示)。然后,我们将该点放置在容器内部,根据容器的大小,从左上角算起30% 30%

从这个逻辑中,我们可以识别出一些简单的情况,例如

          50% 50% (中间)            100% 100% (右下)             100% 0% (右上)

不同立场

以下是常见价值观及其等价性的完整列表:

  • left= left center= center left=0 50%
  • right= right center= center right=100% 50%
  • top= top center= center top=50% 0
  • bottom= bottom center= center bottom=50% 100%
  • center= center center=50% 50%
  • top left= left top=0% 0%
  • top right= right top=100% 0
  • bottom left= left bottom=0 100%
  • bottom right= right bottom=100% 100%

现在很明显,如果图像的大小等于容器的大小,那么使用百分比值不会有任何变化,因为所有位置都是相等的。图像的左上角已经位于0% 0%容器的左上角( ),中心也已经位于中心( 50% 50%),等等。

🏆 使用百分比值时的第一条黄金法则是:图像的大小需要与容器的大小不同

那么渐变呢?

上述逻辑应用于渐变时也是一样的,因为渐变被视为图像。默认情况下,如果你不指定background-size,渐变的大小将等于其容器 的大小,这与使用图像时不同。这是每个开发人员在处理渐变时面临的主要问题。

如果我们参考规范background-size,我们可以看到问题是如何产生的:

如果两个值都是 auto ,则应使用图像的固有宽度和/或高度(如有),缺失的尺寸(如有)如上所述以 auto 的方式处理。如果图像既没有固有宽度也没有固有高度,则其大小将按照contain的方式确定

包含

将图像缩放到最大尺寸,同时保留其固有纵横比(如果有),以便其宽度和高度都可以适合背景定位区域。

还有:

位图图像(例如 JPG)始终具有固有的尺寸和比例。

CSS没有固有尺寸或固有<gradient>比例ref

图像始终具有固有值,因此在大多数情况下,它的尺寸与其容器不同,因此background-position使用百分比单位会产生效果。渐变没有固有值,因此渐变的尺寸等于其容器的尺寸,除非我们指定与容器尺寸不同的值,background-position否则使用百分比单位永远不会起作用。background-size

🏆 使用随机值时的第二条黄金法则是:使用渐变时始终定义背景大小


更深入

我们在上面的例子中看到了使用介于background-size之间的值时如何工作,但是使用负值或大于 的值时又如何呢?逻辑是一样的,但找到参考点会更加棘手。0%100%100%

负值(< 0%)

假设我们想在 处放置一个背景-50% 0。在这种情况下,参考点将位于图像之外。以下是示例:https://jsfiddle.net/no87qv2r/4/

如图所示,我们首先考虑-50%图像的 ,即-50px,来定义我们的参考点(即-50px从图像的左边缘开始)。然后,我们-50%根据容器的大小将该点放置在 (-100px从容器的左边缘开始)。然后我们绘制图像,就得到了上述结果。只有100px的图像可见。

我们可能还会注意到,当图像尺寸小于容器尺寸时,负百分比值的行为与负固定值相同(两者都会使图像向左移动)。在本例中,与( https://jsfiddle.net/no87qv2r/5/-50% 0 )相同-50px 0

例如,如果我们将图像尺寸增加到150px 150px-50% 0将与相同-25px 0

当我们使尺寸大于容器时,负值将开始将图像向右移动(就像正像素值一样),这是合乎逻辑的,因为50%图像的尺寸会增加,而50%容器的尺寸将保持不变。

如果我们考虑上图的情况,这就像增加顶部绿线,直到它比底部绿线更大。所以,仅凭符号不足以了解图像将如何移动;我们还需要考虑尺寸。

从逻辑上讲,这同样适用于渐变:

在上面,请注意以下语法的用法

background:linear-gradient(to right,red,blue) -50% 0/50px 150px no-repeat

这意味着

background:[image or gradient] [background-position]/[background-size] no-repeat

大值(> 100%)

与之前的逻辑相同:如果我们在 处定义背景,那么我们从左边缘(或从右边缘)150% 0考虑我们的参考点,然后我们将它放置在容器的左边缘:https://jsfiddle.net/no87qv2r/9/(在此示例中,相当于150%50%150%150% 0150px 0

如果我们开始增加,background-size我们将会有与之前演示相同的行为:

特殊情况

使用范围之外的值[0% 100%]可以让我们隐藏背景图像,但我们如何找到精确的值来完全隐藏图像呢?

让我们考虑下面的例子:

我们的图像有一个宽度Ws,容器也有一个宽度Wp,我们需要找到的值p。从图中我们可以得到以下公式:

p * Wp = p * Ws + Ws <=> p = Ws/(Wp - Ws) with p in [0,1]

如果容器大小为200px且图像为100px则 p 也是1如此100%(我们当然添加负号并且它是-100%)。

如果我们考虑百分比值而background-size不是固定值,我们可以使这个公式更通用。假设background-sizeS%。那么我们将得到

Ws = Wp * s (s in [0,1] and S=s*100)

第一个公式是:

p = Ws/(Wp - Ws) <=> p = s / (1 - s)

我们加上负号,得到p = s / (s - 1)

现在,如果我们想隐藏右侧的图像,我们会在右侧执行相同的逻辑(我们考虑上一个插图的镜像),但由于我们总是会考虑左边缘来找到我们需要添加的百分比100%

我们定义p'%为等于100% + p%,公式为

p' = 1 + p <=> p' = 1 + s / (1 - s) = 1 / (1 - s)

以下动画演示了上述计算:

让我们计算一些值:

当 时s=0.5, 等于,百分比值将从。在这种情况下,我们从负值开始,以正值结束,因为图像的大小background-size小于容器的大小。如果我们考虑最后一种情况(),等于,百分比值将从。我们从正值开始,以负值结束,因为图像的大小大于容器的大小。50%-100%200%s=2background-size200%200%-100%

🏆 我们有第三条黄金法则:要将图像向左移动,如果尺寸小于容器尺寸,则需要负值,但如果尺寸大于容器尺寸,则需要正值(右侧也一样)

像素和百分比值之间的关系

让我们定义一种根据像素值计算百分比值的方法,反之亦然(即两者之间的转换公式)。为此,我们只需要考虑参考点。

当使用像素值时,我们将考虑蓝线,并且我们将得到background-position:X Y

当使用百分比值时,我们将考虑绿线,并且我们将得到background-position:Px Py

公式如下:X + Px * Ws = Px * Wp其中Ws是图像的宽度,Wp是容器的宽度(考虑到高度,Y 轴的公式相同)。

我们将得到X = Px * (Wp - Ws)。通过这个公式,我们可以验证之前解释的黄金法则:

  • 当 时Wp = Ws,公式不再有效,这证实了当图像的大小与容器相同时百分比值不起作用;因此像素和百分比值之间没有关系。
  • X当 时,和的Px符号相同;Wp > Ws当 时,和 的符号相反Wp < Ws。这证实了百分比值会根据图像大小而有所不同。如果我们考虑 的百分比值,我们也可以以不同的方式表达公式background-size。我们将得到X = Px * Wp * (1 - s)

以下动画演示了上述计算:

更改参考

在上面的计算中,我们始终考虑图像和容器的左上角,以便将逻辑应用于像素值或百分比值。可以通过向 中添加更多值来更改此参考值background-position

默认情况下,background-position: X Y相当于background-position: left X top Y(左侧 X 轴和顶部 Y 轴的位置)。通过调整top和/或,left我们可以更改参考点和图像的放置方式。

以下是一些示例:

显然,对于 的X值,我们只能使用leftright(水平位置),而对于 的Y值,我们只能使用bottomtop(垂直位置)。通过所有不同的组合,我们逻辑上可以得到 4 个不同的角。

此功能还有助于优化某些计算。在特殊情况部分的示例中,我们进行了第一次计算以隐藏左侧图像,然后又进行了另一次计算以隐藏右侧图像。如果我们考虑更改参考,则只需进行一次计算。我们采用左侧使用的公式,并在右侧使用相同的公式。

这是新版本:

因为s=0.5我们不再会从-100%到 制作动画200%,而是从left -100%right -100%

下面是另一个使用像素值的示例,我们可以看到在改变参考时处理计算是多么容易:

通过保持相同的参考来实现相同的动画会很棘手。

🏆 另一条黄金法则:如果您想要一个对称的动画,请在一侧执行逻辑,并通过更改参考在另一侧使用相同的逻辑

结合像素和百分比值

我们可以用它calc()进行一些涉及不同单位的复杂计算。例如,我们可以这样写width:calc(100px + 20% + 12em),浏览器会根据每个单位的工作原理来计算计算值,最终得到一个像素值(在本例中)。

那怎么办background-position?如果我们写calc(50% + 50px),它会被计算为百分比值还是像素值?像素值会转换为百分比吗?还是反过来?

结果不会转换为像素值或百分比值,而是两者一起使用。background-position在混合百分比和像素值时有特殊行为calc(),逻辑如下:

  1. 我们首先通过应用与百分比值相关的所有逻辑,使用百分比值来定位图像。
  2. 我们将 (1) 的位置作为参考,并通过应用与像素值相关的所有逻辑,使用像素值再次定位图像。

做法是:将图像置于中心,然后向左calc(50% + 50px)移动。50px

这个特性可以简化很多计算。以下是一个例子:

找到正确的百分比或像素值来放置如上所示的 4 个红色方块会很繁琐,但通过混合使用则calc()非常容易。

现在,假设我们有这样的内容:calc(10% + 20px + 30% + -10px + 10% + 20px)。浏览器将如何处理这个问题?

在这种情况下,浏览器将首先评估每个单元以获得简化形式calc(X% + Ypx),然后应用上述逻辑来定位图像。

calc(10% + 20px + 30% + -10px + 10% + 20px) 
calc((10% + 30% + 10%) + (20px + -10px + 20px)) 
calc(50% + 30px)
Enter fullscreen mode Exit fullscreen mode

例如:https://jsfiddle.net/no87qv2r/17/

无论公式的复杂程度如何,浏览器总是会分别评估百分比和像素值。

如果我们考虑的话,这里有更多等效值calc()

  • left X top Y=X Y
  • right X top Y=calc(100% - X) Y
  • left X bottom Y=X calc(100% - Y)
  • right X bottom Y=calc(100% - X) calc(100% - Y)

X像素值Y不是百分比!

使用 background-origin

这是另一个可用于更改背景图像位置的重要属性。此属性依赖于盒子模型,因此让我们快速回顾一下它的工作原理:

每个元素内部都有 3 个不同的框:边框框、填充框和内容框。background-origin指定我们需要考虑哪个框来完成所有先前的计算。

这是一个不言自明的例子:

很明显,当我们没有padding时content-box等同于padding-box,当我们没有border时border-box等同于padding-box,而当没有padding和border时,这三者都是等价的。

值得注意的是,background-size当与百分比值一起使用时,会受到此属性的影响。

我们也有这个background-clip属性,但它不会影响计算。它只会通过裁剪部分背景来影响视觉效果。

使百分比表现得像像素

如果我们需要使图像(或渐变)的大小等于容器大小并使用像素等百分比移动它,我们可以考虑以下想法。

使用伪元素作为背景层

需要注意的是,translate 会考虑伪元素的大小,但由于它与容器本身相同,因此不会出现任何问题。我们也可以使用left/ top,但transform性能会更好。使用这种方法不会出现重复。

使用 background-origin

诀窍是使用一些填充,限制原点content-box并使其尺寸大于100%覆盖填充,然后让图像再次填充容器。

在上面的例子中,我将填充设置为大小的一半,因此从逻辑上讲,我需要使用200%background-size进行校正。对于background-position,现在根据前面的解释,很容易找到所需的值。

另一个例子:

使用这种方法,我们可以实现重复,但由于我们添加了填充,所以我们无法添加内容。为了解决这个问题,我们可以结合这两种方法,得到以下效果:

就是这样!

现在background-position对你来说已经没有任何秘密了。👌


给我买杯咖啡

或者

成为赞助人

文章来源:https://dev.to/this-is-learning/all-you-need-to-know-about-background-position-3aac
PREV
Chrome Debugger 比你想象的更容易使用
NEXT
改进 GitHub 代码评审的 5 个技巧