简体   繁体   中英

CSS relative position left works, but top doesn't

I'm trying to position arbitrary elements arbitrarily within an arbitrary container. I want to specify a position as a percentage where

  • 0% means "left edge aligned with the left of the container,"
  • 100% means "right edge aligned with the right of the container,"
  • Any value in between is linearly interpolated, so 50% would be "middle aligned with middle"

To achieve this, the container has position: relative; . The element has position: absolute; with left and top equal to the percentages - these percentages will be relative to the container's size. Then, the element's contents are shifted back with position: relative; and left and top equal to negative the percentage, as this will be relative to the element's size.

Demo:

 #container { position: relative; width: 200px; height: 150px; background-color: #cfc; } #item { position: absolute; left: 80%; top: 80%; background-color: #fcc; } #item>img { position: relative; display: block; left: -80%; top: -80%; } 
 <div id="container"> <div id="item"> <img src="//placehold.it/100x100" /> </div> </div> 

In the demo, the green box is the container, the red box is the element's "real" position, while the placeholder image is the actual content. The coordinate used here is (80%,80%) making it appear in the lower-right corner.

As you can see, the left component works absolutely fine. It is exactly where it should be. The top , however, is not doing the "shift back" thing. It's not moving at all.

Of course there are many similar questions, but all of the ones I've seen stem from the "relative to" element being the relative one, not the absolute , which meant the container had zero height - fair enough. Indeed, explicitly setting the height on my red box in the demo fixes the issue. However, did I mention how arbitrary these components are? I cannot explicitly set the height of the element, I need it to vary based on the content, which may change dynamically.

Any ideas how I might go about this?

As already noticed, the main issue here is that top with percentage values will only work if the parent has a height specified which is not the case here. So in order to fix this we need to find a way to give the item a specified height equal to its content height and different from auto .

And idea would be to consider another div within the #item and make this one a flex container. This will make the new div to be stretched and have a height specified (yes flex is magic) thus the top value on the img will work fine.

 #container { position: relative; width: 200px; height: 150px; background-color: #cfc; overflow:hidden; } #item { position: absolute; display:flex; animation: change-1 1s linear infinite alternate; } #item img { position: relative; display: block; animation: change-2 1s linear infinite alternate; } @keyframes change-1 { from { top:0%; left:0%; } to { top:100%; left:100%; } } @keyframes change-2 { from { top:0%; left:0%; } to { top:-100%; left:-100%; } } 
 <div id="container"> <div id="item"> <div> <img src="//placehold.it/100x100" > </div> </div> </div> 

Here you can use transform property to the placeholder and give value to x and y coordinates the same ie -80%. Hope this helps you out.

 #container { position: relative; width: 200px; height: 150px; background-color: #cfc; } #item { position: absolute; left: 80%; top: 80%; background-color: #fcc; } #item>img { position: relative; display: block; transform: translate(-80%,-80%); } 
 <div id="container"> <div id="item"> <img src="//placehold.it/100x100" /> </div> </div> 

You should specify a height of the parent element :)


UPDATE You can also try to set for your img a negative margin-top: -80% instead of top: 80% , and set the margin-bottom: 80% to preserve parent element height:

 #container { position: relative; width: 200px; height: 150px; background-color: #cfc; } #item { position: absolute; left: 80%; top: 80%; background-color: #fcc; } #item>img { position: relative; display: block; left: -80%; margin-top: -80%; margin-bottom: 80%; } 
 <div id="container"> <div id="item"> <img src="//placehold.it/100x100" /> </div> </div> 

The only trick is that margin in percents is setting relative to the parent element width, so, obviously, if you will have not square image, it will work incorrectly.

I have "resolved" the issue by having JavaScript set margin-left and margin-top based on the pixel size of the content, and added event handlers for the window resizing and the content changing. While this works, I don't like it. A CSS-only solution would trump this by far.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM