惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
N
News and Events Feed by Topic
T
Tailwind CSS Blog
WordPress大学
WordPress大学
罗磊的独立博客
博客园 - 三生石上(FineUI控件)
J
Java Code Geeks
B
Blog RSS Feed
L
LangChain Blog
雷峰网
雷峰网
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 【当耐特】
博客园 - Franky
T
Tor Project blog
C
Cisco Blogs
A
About on SuperTechFans
Spread Privacy
Spread Privacy
博客园 - 司徒正美
T
Threatpost
Engineering at Meta
Engineering at Meta
Forbes - Security
Forbes - Security
阮一峰的网络日志
阮一峰的网络日志
Recorded Future
Recorded Future
宝玉的分享
宝玉的分享
O
OpenAI News
N
News | PayPal Newsroom
博客园 - 聂微东
美团技术团队
Help Net Security
Help Net Security
人人都是产品经理
人人都是产品经理
D
DataBreaches.Net
G
Google Developers Blog
S
Schneier on Security
Hacker News: Ask HN
Hacker News: Ask HN
AWS News Blog
AWS News Blog
H
Hacker News: Front Page
Cloudbric
Cloudbric
Project Zero
Project Zero
V
Visual Studio Blog
F
Full Disclosure
The Last Watchdog
The Last Watchdog
K
Kaspersky official blog
S
SegmentFault 最新的问题
P
Palo Alto Networks Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
Secure Thoughts
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
SecWiki News
SecWiki News
P
Proofpoint News Feed
Know Your Adversary
Know Your Adversary

CSS Articles by Temani Afif

Get Ready For the Powerful CSS border-shape Property! | CSS-Tricks Let’s Play With Gap Decorations! How to Control Infinite CSS Animations (Part 2 of 2) How to Control Infinite CSS Animations (Part 1 of 2) Two Circles, One Arrow, and Anchor Positioning Making a Responsive Pyramidal Grid With Modern CSS | CSS-Tricks How to Create a CSS-only Elastic Text Effect Making Complex CSS Shapes Using shape() | CSS-Tricks Responsive Hexagon Grid Using Modern CSS | CSS-Tricks Responsive List of Avatars Using Modern CSS (Part 2) | CSS-Tricks Responsive List of Avatars Using Modern CSS (Part 1) | CSS-Tricks Perfectly Pointed Tooltips: To The Corners Perfectly Pointed Tooltips: All Four Sides Perfectly Pointed Tooltips: A Foundation Sequential linear() Animation With N Elements | CSS-Tricks Infinite Marquee Animation using Modern CSS Better CSS Shapes Using shape() — Part 4: Close and Move | CSS-Tricks Drawing CSS Shapes using corner-shape Better CSS Shapes Using shape() — Part 3: Curves | CSS-Tricks Better CSS Shapes Using shape() — Part 2: More on Arcs | CSS-Tricks Better CSS Shapes Using shape() — Part 1: Lines and Arcs | CSS-Tricks Creating Blob Shapes using clip-path: shape() Creating Flower Shapes using clip-path: shape() Custom progress element using the attr() function A CSS-Only Star Rating Component and More! (Part 2) | CSS-Tricks A CSS-Only Star Rating Component and More! (Part 1) | CSS-Tricks How to Create Wavy Boxes Using CSS Full-Bleed Layout with Modern CSS Fancy Menu Navigation Using Anchor Positioning | CSS-Tricks How to Create a Zig-Zag Box Using CSS How to Create Zig-Zag CSS Loaders Using One Element Custom Progress Element Using Anchor Positioning & Scroll-Driven Animations How to Create Filling CSS Loaders Using One Element How to Create Curved-Edge and Rounded-Edge Shapes Using CSS CSS Tricks That Use Only One Gradient | CSS-Tricks How to create Shapes with Inner Curves using CSS Mask Custom Range Slider Using Anchor Positioning & Scroll-Driven Animations How to Get the Width/Height of Any Element in Only CSS How Keyboard Navigation Works in a CSS Game How To Create Cut-Out Shapes using The clip-path property The Modern Guide For Making CSS Shapes — Smashing Magazine css-shape.com: The Ultimate Collection of CSS-only Shapes ⚡️ Sliding 3D Image Frames In CSS — Smashing Magazine CSS Tricks To Master The clip-path Property Creating Wavy Circles with Fancy Animations in CSS Modern CSS Tooltips And Speech Bubbles (Part 2) — Smashing Magazine Do you need a Tooltip or a Speech Bubble? I have created 100 using CSS 😲 Modern CSS Tooltips And Speech Bubbles (Part 1) — Smashing Magazine Creating Flower Shapes using CSS Mask & Trigonometric Functions CSS Shapes: The Triangle The Complex But Awesome CSS border-image Property — Smashing Magazine CSS Tricks to add 3D Effects to your Text CSS Responsive Multi-Line Ribbon Shapes (Part 2) — Smashing Magazine CSS Responsive Multi-Line Ribbon Shapes (Part 1) — Smashing Magazine I have made 100+ CSS-only Ribbon Shapes | The Perfect Collection 🎀 How to create a CSS-only infinite scroll animation Re-Creating The Pop-Out Hover Effect With Modern CSS (Part 2) — Smashing Magazine Re-Creating The Pop-Out Hover Effect With Modern CSS (Part 1) — Smashing Magazine How to Create CSS Ribbon Shapes with a Single Element CSS Shapes: The Ribbon Revealing Images With CSS Mask Animations — Smashing Magazine css-loaders.com: The Biggest Collection of Loading Animations (more than 500 🤯) How To Define An Array Of Colors With CSS — Smashing Magazine CSS effects on images II Shines, Perspective, And Rotations: Fancy CSS 3D Effects For Images — Smashing Magazine What's your Lucky CSS Pattern? Check It Now! How to Add a CSS Reveal Animation to Your Images Modern Layouts using CSS Grid I created 100+ unique CSS patterns | The best collection 🤩 How to Create a Custom Range Slider Using CSS CSS Shapes: The Heart CSS Shapes: Polygon & Starburst A Text Reveal Animation using CSS CSS Tip: learn CSS the easy way! How to build a CSS-only accordion How to create Breadcrumb Navigation with CSS Different Ways to Get CSS Gradient Shadows | CSS-Tricks A CSS-only responsive Stepper component A Fancy Hover Effect For Your Avatar | CSS-Tricks How to make a zoom effect using CSS Creating a Custom Cursor using CSS CSS Infinite 3D Sliders | CSS-Tricks CSS Infinite Slider Flipping Through Polaroid Images | CSS-Tricks How to create a responsive sidebar menu using CSS CSS Infinite and Circular Rotating Image Slider | CSS-Tricks Making Static Noise From a Weird CSS Gradient Bug | CSS-Tricks CSS Grid and Custom Shapes, Part 3 | CSS-Tricks Fancy Image Decorations: Outlines and Complex Animations | CSS-Tricks Fancy Image Decorations: Masks and Advanced Hover Effects | CSS-Tricks Fancy Image Decorations: Single Element Magic | CSS-Tricks How to create an infinite image slider using CSS How to Create Wavy Shapes & Patterns in CSS | CSS-Tricks How I Made a Pure CSS Puzzle Game | CSS-Tricks How to create a Tooltip/Speech Bubble using CSS CSS Grid and Custom Shapes, Part 2 | CSS-Tricks CSS Grid and Custom Shapes, Part 1 | CSS-Tricks Zooming Images in a Grid Layout | CSS-Tricks How to create a CSS-only loader with one element Exploring CSS Grid’s Implicit Grid and Auto-Placement Powers | CSS-Tricks How to create background pattern using CSS & conic-gradient
All you need to know about background-position
Temani Afif · 2021-03-13 · via CSS Articles by Temani Afif

Converting one of my Stack Overflow answer to a post

Table of content

  • Pixel values
  • Percentage values
    • What about gradients?
  • More in-depth
    • Negative values (< 0%)
    • Big values (> 100%)
    • Special cases
  • Relation between pixel and percentage values
  • Changing the reference
  • Combining pixel and percentage values
  • Using background-origin
  • Making percentage behave like pixel

When dealing with background-position we have two common situations:

  1. We use pixel value (the trivial one)
  2. We use percentage value (the tricky one)

Let's start a thoroughly explanation and remove all ambiguity around background-position!

Pixel values

When using pixel values, the reference is the top/left corner of the image, whatever the size is. It's like using top/left with a positioned element:

Note that other units like em, ch, etc, behave the same as px. They are called lengths. Our comparison can be generalized to length vs percentage. All you have to know is how each length is converted to pixels.

Percentage values

When using percentage values, the reference is different from when you use pixel values; it's no longer the top/left corner:

In this case, we need to consider two parameters: the size of the container AND the size of the image. Here is an illustration of how it works (I took a background-position equal to 30% 30%):

percentage

First, we consider the image to find the reference point we will use to place the image. It's the point inside the image that is positioned at 30% 30% from the top/left corner considering the size of the image (like defined with the green lines). Then, we place that point inside the container at 30% 30% from the top/left corner considering the size of the container.

From this logic, we can identify some trivial cases like

          50% 50% (center)            100% 100% (bottom right)             100% 0% (top right)

different position

Here is the full list of the common values and their equivalence:

  • 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%

Now it's clear that if the size of the image is equal to the size of the container then nothing will happen when using percentage values simply because all the positions are equivalent. The top/left of the image is already at the top/left (0% 0%) of the container, the center is already at the center (50% 50%), etc.

🏆 The first gold rule when using percentage values is: the size of the image needs to be different from the size of the container

What about gradients?

The above logic is the same when applied to gradients since gradients are considered images, and by default, if you don't specify a background-size, a gradient's size will be the size of its container, unlike when using an image. This is the main issue that every developer faces when dealing with gradients.

If we refer to the specification of the background-size, we can see how the problem arises:

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.

And

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.

And also:

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

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

An image always has intrinsic values, so in most cases, it won't have the same size as its container, so background-position with percentage units will have an effect. Gradients don't have intrinsic values, thus a gradient's dimensions will be equal to the size of its container, and background-position with percentage values will never work unless we specify a background-size different from its container's dimensions.

🏆 The second gold rule when using perchance values is: when using gradient always define a background-size


More in-depth

We saw in the above examples how background-size works when using values between 0% and 100%, but what about using negative values or a value bigger than 100%? The logic is the same, but finding the reference point will be more tricky.

Negative values (< 0%)

Let's suppose we want to place a background at -50% 0. In this case, the reference point will be outside the image. Here is an example: https://jsfiddle.net/no87qv2r/4/

As we can see in the illustration, we first consider -50% of the image, which is -50px, to define our reference point (i.e., -50px from the left edge of the image). Then we place that point at -50% considering the size of the container (-100px from the left edge of the container). Then we draw the image, and we obtain the above result. Only 100px of the image is visible.

We may also notice that negative percentage values will behave the same as negative fixed values when the size of the image is smaller than the size of the container (both will shift the image to the left). In this case -50% 0 is the same as -50px 0 (https://jsfiddle.net/no87qv2r/5/).

If for example we increase the image size to 150px 150px, -50% 0 will be the same as -25px 0.

When we make the size bigger than the container, negative values will start shifting the image to the right (like with positive pixel values), which is logical since the 50% of the image will increase while the 50% of the container will remain the same.

If we consider the previous illustration, it's like increasing the top green line until it's bigger than the bottom one. So the sign only is not enough to know how the image will be shifted; we need to also consider the size.

The same will logically apply to gradients:

In the above, note the usage of the following syntax

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

which means

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

Big values (> 100%)

Same logic as previously: if we define a background at 150% 0, then we consider our reference point 150% from the left edge (or 50% from the right edge), then we place it 150% from the left edge of the container: https://jsfiddle.net/no87qv2r/9/ (in this example, 150% 0 is equivalent to 150px 0)

If we start increasing the background-size we will have the same behavior as previously demonstrated:

Special cases

Using values outside the range [0% 100%] allows us to hide the background image, but how do we find the exact values to completely hide the image?

Let's consider the below illustration:

Our image has a width Ws and the container a width Wp and we need to find the value of p. From the figure we can obtain the following formula:

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

If the container size is 200px and the image is 100px then p is 1 so 100% (we add of course the negative sign and it's -100%).

We can make this more generic if we consider percentage values with background-size instead of fixed values. Suppose the background-size is S%. Then we will have

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

The first formula will be:

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

We add the negative sign and we get p = s / (s - 1)

Now if we want to hide the image on the right side, we do the same logic on the right (we consider a mirror of the previous illustration), but since we will always consider the left edge to find the percentage we need to add 100%.

We the define p'% to be equal to 100% + p%, and the formula will be

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

Here is an animation to illustrate the above calculation:

Let's calculate some values:

When s=0.5, we have a background-size equal to 50%, and the percentage values will be from -100% to 200%. In this case, we started with a negative value and ended with a positive one because the size of the image is smaller than the size of the container. If we consider the last case (s=2) the background-size is equal to 200%, and the percentage values will be from 200% to -100%. We started with a positive value and ended with a negative one because the size of the image is bigger than the size of the container.

🏆 We have our third gold rule: to shift an image to the left we need negative values if the size is smaller than the size of the container, but we need positive values if the size is bigger than the size of the container (same thing for the right).

Relation between pixel and percentage values

Let's define a way to calculate percentage values based on pixel values, or vice versa (i.e. the formula to convert between both). To do this we simply need to consider the reference points.

When using pixel values, we will consider the blue lines and we will have background-position:X Y.

When using percentage values, we will consider the green lines and we will have background-position:Px Py.

The formula will be as follow: X + Px * Ws = Px * Wp where Ws is the width of the image and Wp is the width of the container (same formula for the Y-axis considering height).

We will have X = Px * (Wp - Ws). From this formula we can validate the gold rules explained previously:

  • When Wp = Ws, the formula is no longer valid, which confirms that percentage values have no effect when the size of the image is the same as the container; thus there is no relation between pixel and percentage values.
  • X and Px will have the same sign when Wp > Ws and will have the opposite sign when Wp < Ws. This confirms that percentage values behave differently depending on the size of the image. We can also express the formula differently if we consider percentage values of background-size. We will have X = Px * Wp * (1 - s).

Here is an animation to illustrate the above calculation:

Changing the reference

In the above calculations, we always considered the top/left corner of the image and the container to apply our logic either for pixel values or percentage values. This reference can be changed by adding more values to background-position.

By default background-position: X Y is equivalent to background-position: left X top Y (position at X from the left and at Y from the top). By adjusting top and/or left we change the reference and how the image is placed.

Here are some examples:

It's clear that with the X value we can only use left and right (the horizontal position) while with the Y value we can only use bottom and top (the vertical position). With all the different combinations we logically obtain the 4 different corners.

This feature is also useful to optimize some calculation. In the example of the special cases section, we did the first calculation to hide the image on the left and then another one to hide it on the right. If we consider changing the reference we only need to do one calculation. We take the formula used for the left side and we use the same on the right side.

Here is the new version:

For s=0.5 we will no more animate from -100% to 200% BUT it will be from left -100% to right -100%.

Here is another example using pixel values where we can see how easy is to deal with the calculation when changing the reference:

It would be tricky to achieve the same animation by keeping the same reference.

🏆 Another gold rule :if you want to have a symmetrical animation, do your logic on one side and use the same on the other side by changing the reference.

Combining pixel and percentage values

We can use calc() to do some complex calculation that involves different units. For example, we can write width:calc(100px + 20% + 12em) and the browser will calculate the computed value considering how each unit works and we will end with a pixel value (for this case).

What about background-position? If we write calc(50% + 50px), will this be evaluated to a percentage value or a pixel value? will the pixel value be converted to a percentage or it's the opposite?

The result will not be converted to a pixel value or a percentage value, but rather both will be used together. background-position has special behavior when mixing percentage and pixel values inside calc() and the logic is as follows:

  1. We first use the percentage value to position the image by applying all the logic related to percentage values.
  2. We consider the position of (1) as the reference and we use the pixel value to position the image again by applying all the logic related to pixel values.

Doing calc(50% + 50px) means: center the image, then shift it by 50px to the left.

This feature can simplify a lot of calculations. Here is an example:

It would be tedious to find the correct percentage or pixel values to place the 4 red squares like above, but by mixing both using calc() it is pretty easy.

Now, let's suppose we have something like this: calc(10% + 20px + 30% + -10px + 10% + 20px). How will the browser handle this?

In such cases, the browser will first evaluate each unit to obtain the simplified form calc(X% + Ypx) and then apply the above logic to position the image.

calc(10% + 20px + 30% + -10px + 10% + 20px) 
calc((10% + 30% + 10%) + (20px + -10px + 20px)) 
calc(50% + 30px)

Example: https://jsfiddle.net/no87qv2r/17/

Whatever the complexity of the formula is, the browser will always evaluate percentage and pixel values separately.

Here is more equivalent values if we consider 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 and Y are pixel values and not percentages!

Using background-origin

Here is another important property that can be used to alter the position of a background image. This property relies on the box model so let's get a quick reminder about how that works:

Each element has 3 different boxes inside it: border-box, padding-box, and the content-box. background-origin specifies which box we need to consider to do all our previous calculations.

Here is a self-explanatory example:

It's clear that when we don't have padding content-box is equivalent to padding-box, when we don't have border border-box is equivalent to padding-box, and with no padding and no border, all the 3 are equivalent.

It's important to notice that background-size is affected by this property when used with percentage values.

We also have the background-clip property but this one doesn't affect the calculation. It only affects the visual result by clipping some part of the background.

Making percentages behave like pixels

In case we need to have the size of the image (or the gradient) equal to the container size and move it using percentages like pixels we can consider the below ideas.

Using pseudo-element as a background layer

We should note that translate considers the size of the pseudo-element but since it's the same as the container we won't have any issue. We can also use left/top but transform will have better performance. Using this method we cannot have repetition.

Using background-origin

The trick is to have some padding, restrict the origin to content-box and make the size bigger than 100% to cover the padding and have the image fill the container again.

In the above, I made the padding equal to half the size so logically I need to use 200% in background-size to rectify. For the background-position, it's now easy to find the needed value based on the previous explanation.

Another example:

Using this method we can have repetition but since we are adding padding we won't be able to add content. To overcome this we can combine both methods to get the following:

That's it!

Now background-position has no more secrets for you. 👌


buy me a coffee

OR

Become a patron