Positioning Upright Element Inside Rotated Container - css

I think this is a math question more than anything else, who knew I'd need to know geometry for CSS.
I have an upright background image inside a rotated container. The image has to cover the container perfectly, and the container itself needs be stuck to the wall so that the user doesn't see the rotation on the side. I want to have dynamic control over the sizing of this element, so I would like everything to be done with percentages.
The blue line is the "wall".
Since the image is upright it has to be quite a bit bigger than its container. I found the formula for this here. That's what it looks like:
So the dimensions are in percentages, what I haven't figured out how to calculate is the various positionings. Without the pixel values I added it looks like this:
So how do I calculate these distances?
Here is my CodePen, it's in SCSS, all the math is done in the code.
body {
padding: 2em 5em;
}
.wrapper {
border-left: 3px solid blue;
}
.wrapper .container {
opacity: 0.7;
width: 300px;
background-color: red;
border-radius: 0 40px 40px 0;
overflow: hidden;
transform: rotate(10deg);
margin-left: -42px;
}
.wrapper .container .sizing-wrapper {
width: 100%;
padding-top: 150%;
position: relative;
}
.wrapper .container .img {
position: absolute;
top: 0;
left: 0;
background: url("http://placekitten.com/300/450") no-repeat right top;
background-size: cover;
height: 110.0573842629%;
width: 124.5280657351%;
transform: rotate(-10deg) ranslateY(-31px) translateX(-32px);
}
<div class="wrapper">
<div class="container">
<div class="sizing-wrapper">
<div class="img"></div>
</div>
</div>
</div>

I shared my question on Facebook and Amit Sheen came up with a solution I initially dismissed of using transform-origin. Now that I've seen it work I'm not sure why I thought it wouldn't.
The fixed CodePen
To make sure the container is cut by the wall at the right place we need to rotate it from the top left corner by using transform-origin: 0 0.
And we need to center the image inside the container:
.img {
top: 50%;
left: 50%;
transform: rotate(-$deg) translateY(-50%) translateX(-50%);
transform-origin: 0 0;
}
I'm still curious what the mathematical solution to my question is, because I'm sure there is one, but for actual use this is probably better...
body {
padding: 2em 5em;
}
.wrapper {
border-left: 3px solid blue;
}
.wrapper .container {
opacity: 0.7;
width: 300px;
background-color: red;
border-radius: 0 40px 40px 0;
overflow: hidden;
transform: rotate(10deg);
transform-origin: 0 0;
}
.wrapper .sizing-wrapper {
width: 100%;
padding-top: 150%;
position: relative;
}
.wrapper .img {
position: absolute;
top: 50%;
left: 50%;
background: url("http://placekitten.com/300/450") no-repeat right top;
background-size: cover;
height: 110.0573842629%;
width: 124.5280657351%;
transform: rotate(-10deg) translateY(-50%) translateX(-50%);
transform-origin: 0 0;
}
<div class="wrapper">
<div class="container">
<div class="sizing-wrapper">
<div class="img"></div>
</div>
</div>
</div>

Related

CSS Vertically position an image [duplicate]

This question already has answers here:
How can I vertically center a div element for all browsers using CSS?
(48 answers)
How can I center an absolutely positioned element in a div?
(37 answers)
Flexbox: center horizontally and vertically
(14 answers)
Closed last year.
I would like to be able to position the gray container in the middle of the background, also vertically, but I can't understand how the percentages work, why the left one works and the top doesn't
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
html {
font-size: 62.5%;
}
body {
background-image: url("wallpaper.png");
background-size: cover;
background-repeat: no-repeat;
position: relative;
top: 0px;
}
.container {
background-color: lightgray;
opacity: 50%;
width: 200px;
height: 200px;
left: calc(50% - 100px);
top: calc(50% - 100px);
position: relative;
}
<body>
<div class="container">
<div class="container-name"></div>
<div class="container-stats"></div>
</div>
</body>
Here is the preview
You need to give the body a height, or else it'll be the elements height, that's why you can't move top or bottom, since the parent (body) is only 200px, since that's all there is. Where the parent doesn't have a height property, it'll automatically adjust to it's content height, 200px in this case. Also, the top property from body can be removed.
You could add height: 100vh; to your body, that'll be the 100%/units height of the view port.
The calc() function you have is taking 50% of it's parent size, then substracting 100px, which in your case is 50% of your element. That'll center the element with percentages.
An alternative to your centering solution could be:
.container {
background-color: lightgray;
opacity: 50%;
width: 200px;
height: 200px;
left: 50%;
top: 50%;
position: relative;
transform: translate(-50%, -50%);
}
This will move your container 50% left of parents width, 50% from the top of parent and then, with transform: translate() move it -50% of it's own size X and Y
You need to give a height to body.
If parent div has a position relative then for setting div according to parent you should give a child div to position absolute.
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
html {
font-size: 62.5%;
}
body {
background-image: url("wallpaper.png");
background-size: cover;
background-repeat: no-repeat;
position: relative;
top: 0px;
height: 100vh;
}
.container {
background-color: lightgray;
opacity: 50%;
width: 200px;
height: 200px;
left: 50%;
top: 50%;
position: absolute;
transform: translate(-50%, -50%);
}
<div class="container">
<div class="container-name"></div>
<div class="container-stats"></div>
</div>
HTML:
<div class="wrap-center">
<div class="container">
<div class="container-name"></div>
<div class="container-stats"></div>
</div>
</div>
CSS:
.container {
background-color: lightgray;
opacity: 50%;
width: 200px;
height: 200px;
}
.wrap-center {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
min-height: 500px;
}

Draw a line through a circle

I'm getting trouble with drawing a line through a circle.
I'd like to have a line that also adapt to the div height, this is what I tried so far :
<html>
<body>
<div class="item">
<div class="item__level opacity-10">
<div class="item__level__round"></div>
<div class="item__level__line"></div>
</div>
</div>
</body>
</html>
And CSS
.item{
width: 100%;
height: 40px;
}
.item__level{
width: 10%;
position: relative;
height: 100%;
}
.item__level__round{
width: 20px;
height: 20px;
background: #1F8AEE;
border-radius: 50%;
position: absolute;
transform: translateX(50%) translateY(50%);
}
.item__level__line{
position: absolute;
border-left: 2px solid red;
left: 12%;
top: 0;
height: 100%;
}
https://codepen.io/anon/pen/eQMdjm
It seems like the red line is not perfectly in the center of the circle, is it an optic illusion ? I'm on this since a while
update - Sorry, I just reread your question. Yea the line could be off by a pixel depending on the widths. Check this fiddle for an example https://jsfiddle.net/Hastig/pzo4fe2a/ (red line is 20px wide and blue line is 21px. It doesn't cut a pixel in half so the full 1px difference appears to the right (in FF) instead of a half pixel on left and the second half on right. If you're doing percentage widths and heights the issue can occur in responsive design because you can't control the device width.
original answer - Try adding left: 50% and top 50% to your circle and line and use the -50% to compensate and keep it centered.
.container {
display: relative;
width: 100vw;
height: 100vh;
}
.circle {
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
width: 100px;
height: 100px;
background-color: skyblue;
border-radius: 100%;
}
.line {
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
width: 2%;
height: 100%;
background-color: skyblue;
}
<div class="container">
<div class="circle"></div>
<div class="line"></div>
</div>
Play with the fiddle pane to see it respond to viewscreen size.
https://jsfiddle.net/Hastig/7d8ebqxm/

Center fixed element horizontally minus column

I have a two-column layout and want a fixed element to be centered horizontally in the right column.
How do I accomplish this as a fixed element isn't position relative to it's parent but rather to the document?
Note: the left column's width is known. The right column's width is "full width".
I'm using fixed (and not absolute) because the element has to follow scrolling.
.wrapper {
height: 200px;
display: flex;
background-color: green;}
.column {
width: 300px;
background-color: pink;
}
.content {
flex: 1;
background-color: green;
}
.fixed-element {
position: fixed;
left: 50%;
background-color: orange;
}
<div class='wrapper'>
<div class='fixed-element'>Please center me in green area.</div>
<div class='column'></div>
<div class='content'></div>
</div>
You can use calc to calculate center and transform for the unkown width of fixed element positioning.
Please check if the browser compability for the calc is ok for you, before using it in production.
And here is my solution
body {
margin: 0;
}
.wrapper {
height: 200px;
display: flex;
background-color: green;
}
.column {
width: 200px;
background-color: pink;
}
.content {
flex: 1;
background-color: maroon;
}
.fixed-element {
z-index: 111;
position: fixed;
right: calc(50% - 205px); //can't explain that +5px :)
-webkit-transform: translateX(-50%);
-moz-transform: translateX(-50%);
-ms-transform: translateX(-50%);
-o-transform: translateX(-50%);
transform: translateX(-50%);
background-color: orange;
}
<div class='wrapper'>
<div class='fixed-element'>Please center me</div>
<div class='column'></div>
<div class='content'></div>
</div>

Slightly arced footer with CSS

I have made a footer in Photoshop looking like this:
As you can see, the footer here is slightly arced all the way across. I have tried doing something with border-radius, but that almost only targets the edge, which makes the arc more curved in the edges, and not even receiving the effect of a subtle arced footer as seen in the image.
Is there an easy CSS way to do this, or do I need some JavaScript or something to achieve this?
Use a pseudo element of the footer with border-radius to make the arch.
I made them different colors here so you can see which element is which.
body {
margin: 0;
max-height: 100vh;
overflow: hidden;
}
footer {
bottom: 0; left: 0; right: 0;
position: absolute;
background: brown;
height: 10vh;
}
footer::before {
content: '';
background: red;
width: 200%;
position: absolute;
left: 50%;
top: -100%;
transform: translateX(-50%);
height: 1000%;
border-radius: 50%;
z-index: -1;
}
<footer></footer>
This solution uses a large width to get a more pleasant curve, but without the pseudo-element:
footer {
background-color: red;
width: 200%;
transform: translateX(-25%);
height: 200px;
border-radius: 50% 50% 0 0;
}
<div>
<footer></footer>
</div>
Its not perfect, but here i've got a really really big circle that's absolutely positioned with the overflow hidden so that you only see the top part of the arc.
#container{
background: grey;
height:300px;
width:500px;
position:relative;
overflow:hidden;
}
#arc{
position: absolute;
top:200px;
left:-800px;
width:2000px;
height:2000px;
border-radius:2000px;
background:brown;
}
<div id="container">
<div id="arc">
</div>
</div>
https://jsfiddle.net/z9pq1026/
You can actually use border-radius to do this without a pseudo element.
.arc {
width: 100%;
height:500px;
background: #000000;
border-radius: 50% / 30px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
<div class="arc"></div>
will work just fine. Make sure that when you use:
border-radius: 50% / 30px;
the first property is always "50%" as this will ensure the arc meets in the middle. The second property (after the "/") is the height of the arc measured from the middle to the edges
The circle solution, but it's responsive!
footer {
background: #ececec;
height: 200px;
width: 100%;
position: relative;
overflow: hidden;
}
.arc {
position: absolute;
top: 0px;
right: calc(-80%);
width: 300%;
padding-top: 100%;
border-radius: 100%;
background: black;
}
<footer>
<div class="arc">
</div>
</footer>

How to center crop a full screen background image

Stack Overflow seems to be full of similar questions but I haven't found a satisfying answer for my use case. Basically, I need a responsive, full screen background image for the top part of my front page. Means, narrowing the viewport leads to cropping, not stretching; the image should be centered. I'd like to avoid JS for this.
Aaron created a fiddle that almost looks like what I'm searching for. Two problems:
Strange behaviour when narrowing viewport (below 500px width)
position: fixed;
I was able to reproduce the solution of Bryce Hanscomb and Gabriela Gabriel for a container (see my fiddle):
But I failed to extend this to full screen. This is my code (see fiddle):
HTML:
<div id="background">
<img src="//dummyimage.com/600x200/0099cc/fff.png" />
</div>
CSS:
div#background {
background-color: orange;
min-height: 100%;
min-width: 100%;
overflow: hidden;
position: absolute;
top: 0;
z-index: -1;
}
img {
left: 50%;
position: relative;
transform: translate(-50%, 0);
min-height: 100%;
min-width: 100%;
}
Problem #1: The image doesn't take up the full height of its parent div (with min-height set to 100%).
Problem #2 + #3: In a narrow viewport, the image is cut off on the right (not centered), and a horizontal scrollbar is shown.
As a side note, can somebody tell me where those 4 pixels come from?
Your image will fill the entire space and also not have the problem of not being centered if you use position:absolute on your image
div#background {
background-color: orange;
min-height: 100%;
min-width: 100%;
overflow: hidden;
position: absolute;
top: 0;
z-index: -1;
}
img {
left: 50%;
position: absolute;
transform: translate(-50%, 0);
min-height: 100%;
min-width: 100%;
}
The issue with the 4px at the bottom is because images always align to the top just like text, this also adds a bit of padding to the bottom to make the baseline for the text so that letters can hang down under the rest.
If you set vertical-align: bottom it should fix it like so:
h1 {
text-align: center;
}
div#container {
background-color: black;
height: 200px;
width: 100%;
margin: 50px auto;
}
div#content {
background-color: orange;
min-width: 100%;
overflow: hidden;
}
img {
left: 50%;
position: relative;
transform: translate(-50%, 0);
vertical-align: bottom;
}
<div id="container">
<div id="content">
<img src="//dummyimage.com/600x200/0099cc/fff.png" />
</div>
</div>
For the centre aligning of the image, I would personally recommend actually using css background-image and then setting the background-position like so:
div#background {
background-color: orange;
min-height: 100%;
min-width: 100%;
position: absolute;
top: 0;
z-index: -1;
background: url(//dummyimage.com/600x200/0099cc/fff.png) center center no-repeat;
background-size: cover;
}
<div id="background">
</div>

Resources