gpt4 book ai didi

css - 在线性梯度上使用背景位置的百分比值

转载 作者:行者123 更新时间:2023-12-03 07:33:16 24 4
gpt4 key购买 nike

有什么方法可以让background-position接受百分比值?目前,我的按钮仅适用于widthbackground-position的显式值。

body {
min-height: 100vh;
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
}

.button {
display: flex;
justify-content: center;
align-items: center;
text-decoration: none;
color: white;
font-weight: bold;
width: 350px;
height: 50px;
border: 1px solid green;
transition: background 0.5s;
background-repeat: no-repeat;
background-image: linear-gradient(to left, #2484c6, #1995c8 51%, #00bbce), linear-gradient(to right, #2484c6 0%, #1995c8 51%, #00bbce 76%);
}
.button-pixel {
background-position: -350px 0px, 0px 0px;
}
.button-pixel:hover {
background-position: 0px 0px, 350px 0px;
}
.button-percentage {
background-position: -100% 0px, 0px 0px;
}
.button-percentage:hover {
background-position: 0% 0px, 100% 0px;
}
<a href="#" class="button button-pixel">In Pixel</a>
<a href="#" class="button button-percentage">In Percentage</a>

最佳答案

TL; DR

当使用渐变作为背景时,与background-position 一起使用的所有百分比值都是等效的,因此不会有任何区别。您需要指定与容器大小不同的background-size:

body {
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
min-height:90vh;
}

.button {
text-decoration: none;
color: white;
font-weight: bold;
width: 350px;
height: 50px;
text-align:center;
transition: background 0.5s;
background-repeat: no-repeat;
background-image:
linear-gradient(to left, #2484c6, #1995c8 51%, #00bbce),
linear-gradient(to right, #2484c6 0%, #1995c8 51%, #00bbce 76%);
background-size:200% 100%; /*Changed this*/
}
.button-pixel {
background-position: -350px 0px, 0px 0px;
}
.button-pixel:hover {
background-position: 0px 0px, 350px 0px;
}
.button-percentage {
background-position: 100% 0px, 0px 0px;
}
.button-percentage:hover {
background-position: 0% 0px, 100% 0px;
}
<a href="#" class="button button-pixel">Pixel</a>
<a href="#" class="button button-percentage">Percentage</a>



背景职位如何运作?

让我们使用经典图像来解释 background-position的工作原理。

使用像素值时,无论大小如何,引用都是图像的 左上角。就像将 top / left与定位元素一起使用:

.b {
width:200px;
height:200px;
background:url(https://picsum.photos/100/100?image=1069) no-repeat;
border:1px solid;
background-position:0 0;
position:relative;
animation:back 5s infinite linear alternate;
}
.b:before {
content:"";
position:absolute;
top:0;
left:0;
width:10px;
height:10px;
background:red;
animation:change 5s infinite linear alternate;
}

@keyframes back{to{background-position:200px 200px;}}
@keyframes change{to{top:200px; left:200px;}}
<div class="b"></div>


使用百分比值时,引用不同于使用像素值时的引用;它不再是左上角:

.b {
width:200px;
height:200px;
background:url(https://picsum.photos/100/100?image=1069) no-repeat;
border:1px solid;
background-position:0% 0%;
position:relative;
animation:back 3s infinite linear alternate;
}
.b:before {
content:"";
position:absolute;
top:0;
left:0;
width:10px;
height:10px;
background:red;
animation:change 3s infinite linear alternate;
}
@keyframes back{to{background-position:100% 100%;}}
@keyframes change{to{top:200px; left:200px;}}
<div class="b"></div>


在这种情况下,我们需要考虑两个参数:容器的大小和图像的大小。这是它如何工作的说明(我接受了一个等于 background-position30% 30%):

enter image description here

首先,我们考虑图像以找到将用于放置图像的引用点。考虑到 图像的大小(如用绿线定义的),这是图像内的 点位于从左上角到30% 30%的位置。然后,考虑到容器的大小,将该点放置在容器内从左上角到30% 30%50% 50%处。

通过这种逻辑,我们可以清楚地识别出一些琐碎的情况,例如
100% 100%(中间)100% 0%(右下)background-size(右上)

enter image description here

现在很明显,如果图像的大小等于容器的大小,则仅由于所有位置都等于而不会发生任何事情。图像的顶部/左侧已经在容器的顶部/左侧(0%0%),中心已经在容器的中心(50%50%),依此类推。

.b {
width:200px;
height:200px;
background:url(https://picsum.photos/200/200?image=1069) no-repeat;
border:1px solid;
background-position:0% 0%;
position:relative;
animation:back 5s infinite linear alternate;
}
.b:before {
content:"";
position:absolute;
top:0;
left:0;
width:10px;
height:10px;
background:red;
animation:change 5s infinite linear alternate;
}
@keyframes back{to{background-position:100% 100%;}}
@keyframes change{to{top:100%; left:100%;}}
<div class="b"></div>



应用于渐变时,上述逻辑是相同的,因为渐变被视为图像,并且默认情况下,如果不指定background-size,则渐变的大小将为其容器的大小,这与使用图像不同。

如果我们引用background-positionspecification,我们可以看到您的问题是如何产生的:

If both values are auto then the intrinsic width and/or height of the image should be used, if any, the missing dimension (if any) behaving as auto as described above. If the image has neither an intrinsic width nor an intrinsic height, its size is determined as for contain.



和:

contain

Scale the image, while preserving its intrinsic aspect ratio (if any), to the largest size such that both its width and its height can fit inside the background positioning area.



并且:

A bitmap image (such as JPG) always has intrinsic dimensions and proportions.

CSS <gradient>s have no intrinsic dimensions or intrinsic proportions.ref



图像始终具有固有值,因此在大多数情况下,图像的大小与容器的大小不同,因此具有百分比单位的background-position会起作用。但是渐变没有内在值,因此渐变的尺寸将等于其容器的大小,带有百分比值的background-size永远不会起作用,除非我们指定与其容器尺寸不同的background-size



更深入

在上面的示例中,我们看到了在0%100%之间使用值时100%是如何工作的,但是使用负值或大于-50% 0的值又如何呢?逻辑是相同的,但是找到引用点会比较棘手。

负值(<0%)

假设我们要在-50%放置背景。在这种情况下,引用点将在图像之外。这是一个例子:

.b {
width:200px;
height:200px;
border:1px solid;
background:url(https://picsum.photos/100/100?image=1069) -50% 0/100px 100px no-repeat;
}
<div class="b"></div>


enter image description here

正如我们在插图中看到的,我们首先考虑图像的-50px,即-50%,以定义我们的引用点(即,从图像左边缘起-50px)。然后,考虑容器的大小(距离容器左边缘100像素),将该点放置在100px上。然后我们绘制图像,并获得以上结果。仅图像的-50% 0是可见的。

我们还可能注意到,当图像的大小小于容器的大小时,负百分比值将与负固定值具有相同的作用(两者都会将图像向左移动)。在这种情况下,-50px 0150px 150px相同。

.b {
width:200px;
height:200px;
display:inline-block;
border:1px solid;
background:url(https://picsum.photos/100/100?image=1069) -50% 0/100px 100px no-repeat;
}
.a{
background:url(https://picsum.photos/100/100?image=1069) -50px 0/100px 100px no-repeat;
}
<div class="b">
</div>
<div class="b a">
</div>


例如,如果我们将图像大小增加到-50% 0-25px 0将与50%相同。

当我们将的大小设置为大于容器时,负值将开始将图像向右移动(与正像素值一样),这是合乎逻辑的,因为图像的50%将增加,而容器的150% 0将保持相同。

如果我们考虑上一个插图,这就像增加顶部的绿线,直到其大于底部的绿线。因此,仅
符号还不足以知道背景图像将如何移动。我们还需要考虑尺寸。

.b{
width:200px;
height:200px;
border:1px solid;
background:url(https://picsum.photos/300/300?image=1069) -50% 0/50px 50px no-repeat;
animation:change 2s linear infinite alternate;
}
@keyframes change{
to {background-size:300px 300px}
}
<div class="b">
</div>


对于梯度,逻辑上将发生相同的情况:

.b {
width:200px;
height:200px;
border:1px solid;
background:linear-gradient(to right,red,blue) -50% 0/50px 150px no-repeat;
animation:change 2s linear infinite alternate;
}
@keyframes change{
to {background-size:300px 150px}
}
<div class="b">
</div>


大值(> 100%)

与以前的逻辑相同:如果我们在150%定义背景,那么我们从左边缘考虑引用点50%(或从右边缘考虑150%),然后从容器的左边缘放置150% 0

.b {
width:200px;
height:200px;
border:1px solid;
background:url(https://picsum.photos/100/100?image=1069) 150% 0/100px 100px no-repeat;
}
<div class="b"></div>


在这种情况下,150px 0等效于[0% 100%],并且如果我们开始增加背景大小,我们将具有与先前演示的相同的行为:

.b {
width:200px;
height:200px;
border:1px solid;
background:url(https://picsum.photos/300/300?image=1069) 150% 0/50px 50px no-repeat;
animation:change 2s infinite linear alternate;
}
@keyframes change {
to {background-size:300px 300px}
}
<div class="b"></div>



特别案例

使用Ws范围之外的值可以隐藏背景图像,但是如何找到确切的值以完全隐藏图像呢?

让我们考虑下图:

enter image description here

我们的图像的宽度为Wp,容器的宽度为p,我们需要找到200px的值。从图中我们可以得到以下公式:
p * Wp = p * Ws + Ws   <=>   p = Ws/(Wp - Ws)   where p in [0,1]

如果容器的大小是100px,图像是p,那么1100%,所以是-100%(我们当然加上了负号,它是background-size)。

如果我们考虑使用background-size代替固定值的百分比值,则可以使其更通用。假设S%Ws = Wp * s (s in [0,1] and S=s*100%)。然后我们将得到p = s / (s - 1),公式将是
p = Ws/(Wp - Ws)   <=>   p = s / (1 - s)

加上负号将是100%

现在,如果我们想在右侧隐藏图像,则在右侧执行相同的逻辑(我们考虑上图的镜像),但是由于我们将始终考虑左侧边缘以找到百分比,因此需要添加p'%

新的百分比100% + p%p' = 1 + p --> p' = 1 + s / (1 - s) = 1 / (1 - s),公式为s=0.5

这是说明上述计算的动画:

.b {
width:200px;
height:50px;
margin:5px;
border:1px solid;
background:linear-gradient(to right,red,blue) no-repeat;
background-size:calc(var(--s) * 100%) 100%;
animation:change 4s linear infinite alternate;
}
@keyframes change{
from { /*Hide on the left*/
background-position:calc(var(--s)/(var(--s) - 1) * 100%)
}
to { /*Hide on the right*/
background-position:calc(1/(1 - var(--s)) * 100%)
}
}
<div class="b" style="--s:0.5">
</div>
<div class="b" style="--s:0.8">
</div>
<div class="b" style="--s:2">
</div>


让我们计算一些值:

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

这证实了我们之前所说的:将图像向左移动时,如果尺寸较小,则需要负值;但是,如果尺寸较大,则需要正值(右边相同)。

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

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

enter image description here

使用像素值时,我们将考虑蓝线,并使用background-position:Px Py

使用百分比值时,我们将考虑绿线,并使用Y + Py * Ws = Py * Wp

公式如下所示:Ws其中Wp是图像的宽度,Y = Py * (Wp - Ws)是容器的宽度(对于X轴,考虑高度的公式相同)。

我们将拥有Wp = Ws。根据该公式,我们可以验证两点,如前所述:
  • 当使用Y时,该公式不再有效,它可以确认当图像的大小与容器大小相同时,百分比值不起作用。因此像素和百分比值之间没有关系。
  • PyWp > Ws将具有相同的符号,而Wp < Ws时将具有相反的符号。这确认了百分比值的行为取决于图像的大小。

  • 如果考虑background-size的百分比值,我们也可以用不同的方式表达公式。我们将拥有Y = Py * Wp * (1-s)

    这是说明上述计算的动画:

    .b {
    width:200px;
    height:50px;
    margin:5px;
    border:1px solid;
    background:linear-gradient(to right,red,blue) no-repeat;
    background-size:calc(var(--s) * 100%) 100%;
    animation:percentage 2s linear infinite alternate;
    }
    .box.a {
    animation-name:pixel;
    }
    @keyframes percentage{
    from { background-position:-50%;}
    to { background-position:150%;}
    }
    @keyframes pixel{
    from { background-position:calc(-0.5 * 200px * (1 - var(--s))) }
    to { background-position:calc(1.5 * 200px * (1 - var(--s)));}
    }
    <div class="b" style="--s:0.5">
    </div>
    <div class="b a" style="--s:0.5">
    </div>

    <div class="b" style="--s:2">
    </div>
    <div class="b a" style="--s:2">
    </div>



    更改引用

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

    默认情况下,background-position: X Ybackground-position: left X top Y等效(位于XleftYtop的位置)。通过调整top和/或left,我们可以更改引用以及图像的放置方式。这里有些例子:

    .b {
    width:150px;
    height:150px;
    display:inline-block;
    background:url(https://picsum.photos/70/70?image=1069) no-repeat;
    border:1px solid;
    position:relative;
    }

    body {
    margin:0;
    }
    <div class="b"></div>
    <div class="b" style="background-position:left 0 bottom 0"></div>
    <div class="b" style="background-position:right 0 bottom 0"></div>
    <div class="b" style="background-position:right 0 top 0"></div>


    <div class="b" style="background-position:right 10% top 30%"></div>
    <div class="b" style="background-position:right 10% bottom 30%"></div>
    <div class="b" style="background-position:right 10px top 20px"></div>
    <div class="b" style="background-position:left 50% bottom 20px"></div>


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

    为了优化某些计算,此功能也很有用。在特殊情况部分的示例中,我们进行了第一个计算以将图像隐藏在左侧,然后进行另一个计算以将图像隐藏在右侧。如果考虑更改引用,我们只需要进行一次计算即可。我们采用左侧使用的公式,而右侧使用相同的公式。

    这是新版本:

    .b {
    width:200px;
    height:50px;
    margin:5px;
    border:1px solid;
    background:linear-gradient(to right,red,blue) no-repeat;
    background-size:calc(var(--s) * 100%) 100%;
    animation:change 4s linear infinite alternate;
    }
    @keyframes change{
    from {
    background-position:left calc(var(--s)/(var(--s) - 1) * 100%) top 0
    }
    to {
    background-position:right calc(var(--s)/(var(--s) - 1) * 100%) top 0
    }
    }
    <div class="b" style="--s:0.5">
    </div>
    <div class="b" style="--s:0.8">
    </div>
    <div class="b" style="--s:2">
    </div>


    对于s=0.5,我们将不再从-100%动画化为200%,但是将从left -100%动画化为right -100%

    这是另一个使用像素值的示例,在此示例中,我们可以清楚地看到更改引用值时如何轻松地进行计算:

    .b {
    width:200px;
    height:200px;
    background:url(https://picsum.photos/100/100?image=1069) no-repeat;
    border:1px solid;
    background-repeat:no-repeat;
    animation:change 2s infinite linear;
    }


    @keyframes change{
    0%{background-position:left 20px top 20px;}
    25%{background-position:right 20px top 20px;}
    50%{background-position:right 20px bottom 20px;}
    75%{background-position:left 20px bottom 20px;}
    100%{background-position:left 20px top 20px;}
    }
    <div class="b"></div>


    通过保持相同的引用来实现相同的动画将非常棘手。因此,如果我们想进行对称动画处理,则可以通过更改引用在一侧进行逻辑处理,而在另一侧使用相同的逻辑处理。

    组合像素和百分比值

    在CSS3中,我们可以使用calc()来进行一些涉及不同单位的复杂计算。例如,我们可以编写width:calc(100px + 20% + 12em),浏览器将考虑每个单元的工作方式来计算计算值,并以像素值结尾(在这种情况下)。

    background-position呢?如果我们编写calc(50% + 50px),它将被评估为百分比值还是像素值?像素值会转换为百分比还是相反?

    结果不会转换为像素值或百分比值,而是将两者一起使用!在background-position中混合百分比和像素值时,calc()具有特殊的行为,其逻辑如下:
  • 我们首先通过应用与百分比值相关的所有逻辑,使用百分比值来定位图像。
  • 我们将(1)的位置作为引用,并通过应用与像素值有关的所有逻辑,使用像素值再次定位图像。

  • 因此calc(50% + 50px)的意思是:将图片居中,然后将其向左移动50px。

    此功能可以简化很多计算。这是一个例子:

    .b {
    width:200px;
    height:200px;
    display:inline-block;
    border:1px solid;
    background-image:
    linear-gradient(red,red),
    linear-gradient(red,red),
    linear-gradient(red,red),
    linear-gradient(red,red);
    background-size:20px 20px;
    background-position:
    calc(50% + 20px) 50%,
    calc(50% - 20px) 50%,
    50% calc(50% - 20px),
    50% calc(50% + 20px);
    background-repeat:no-repeat;
    transition:0.5s;
    }
    .b:hover {
    background-position:50%;
    }
    <div class="b"></div>
    <div class="b" style="width:100px;height:100px;"></div>


    找到正确的百分比或像素值以放置上面的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)

    .box {
    display:inline-block;
    width:200px;
    height:200px;
    background-image:url(https://picsum.photos/100/100?image=1069);
    border:1px solid;
    background-position:calc(10% + 20px + 30% + -10px + 10% + 20px) 0;
    background-repeat:no-repeat;
    }
    .alt {
    background-position:calc(50% + 30px) 0;
    }
    <div class="box"></div>
    <div class="box alt"></div>


    无论公式的复杂性如何,浏览器始终会分别评估百分比和像素值。

    使用背景起源的

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

    enter image description here

    每个元素内部都有3个不同的框:border-box,padding-box和content-box。 background-origin指定为了执行所有先前的逻辑,我们需要考虑使用哪个框。

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

    .b {
    display:inline-block;
    width:200px;
    height:200px;
    background:
    url(https://picsum.photos/100/100?image=1069) no-repeat,
    linear-gradient(to right,red,blue) bottom/100% 20% no-repeat;
    border:20px solid rgba(0,0,0,0.1);
    padding:20px;
    box-sizing:border-box;

    background-origin:border-box;
    }
    .p {
    background-origin:padding-box; /*the default value*/
    }
    .c {
    background-origin:content-box;
    }
    <div class="b"></div>
    <div class="b p"></div>
    <div class="b c"></div>


    现在应该清楚的是,当我们没有填充content-box时,它等于padding-box;而当我们没有边框时,border-box时,它等于padding-box

    使百分比表现不同

    万一我们确实需要使图像的大小等于容器的大小,并使用像像素这样的百分比来移动它,我们可以考虑以下想法。
  • 使用伪元素作为背景层:


  • .b {
    width:200px;
    height:200px;
    border:1px solid;
    position:relative;
    z-index:0;
    overflow:hidden;
    }
    .b:before {
    content:"";
    position:absolute;
    top:0;
    left:0;
    width:100%;
    height:100%;
    z-index:-1;
    background:url(https://picsum.photos/200/200?image=1069);
    background-size:100% 100%;
    transition:1s;
    }
    .b:hover::before {
    transform:translate(100%,100%);
    }
    <div class="b"></div>


    我们应该注意,translate考虑伪元素的大小,但由于它与容器相同,所以不会有任何问题。我们也可以使用left / top,但是transform将具有更好的性能。
  • 使用background-origin

  • 诀窍是要进行填充,将原点限制在content-box中,并使其大小大于100%来覆盖填充并使图像填充容器。

    .b {
    width:200px;
    height:200px;
    outline:1px solid;
    padding:0 100px 100px 0;
    box-sizing:border-box;
    z-index:0;
    overflow:hidden;
    background:url(https://picsum.photos/200/200?image=1069) no-repeat;
    background-origin:content-box;
    background-size:200% 200%;
    transition:0.8s;
    }

    .b:hover {
    background-position:-200% -200%;
    /* We use [0%,-200%] to cover [0%,100%]*/
    }
    <div class="b"></div>


    在上面,我将填充的大小减半,因此从逻辑上讲,我需要使用200%中的background-size进行纠正。对于background-position,现在可以轻松根据上述说明找到所需的值。

    另一个例子:

    .b {
    width:200px;
    height:200px;
    outline:1px solid;
    padding:50px;
    box-sizing:border-box;
    z-index:0;
    overflow:hidden;
    background:url(https://picsum.photos/200/200?image=1069) no-repeat;
    background-origin:content-box;
    background-size:200% 200%;
    background-position:50% 50%;
    transition:0.8s;
    }

    .b:hover {
    background-position:-150% -150%;
    /* We use [50%,-150%] to cover [0%,100%]*/
    }
    <div class="b"></div>




    请注意,其他单位(如emch等)的行为与px相同。它们称为lengths

    关于css - 在线性梯度上使用背景位置的百分比值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52401059/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com