I'm trying to position an element in the bottom right corner of it's parent. At the moment, you can see it's in the center, but touching the bottom:
http://jsfiddle.net/03r7gabp/
Ideally, I'd like it to be touching the bottom, flushed all the way to the right (what right: 0; typically does).
This is the desired effect:
Is this possible? I'm already using:
transform-origin: bottom left;
There are couple of solutions to achieve that, however I found this one more flexible.
Due to the fact that you can combine multiple transform notations, you'll end up with:
.info {
position: absolute;
bottom: 0; right: 0;
transform: rotate(-90deg) translateX(100%);
transform-origin: 100% 100%;
}
The key point is that a percentage value on translate() notation is relative to the size of bounding box. I.e. the size of border-box of the absolutely positioned element in this case.
Here is a demo:
.container {
width: 300px;
height: 200px;
border: 1px solid red;
position: relative;
}
.info {
position: absolute;
bottom: 0; right: 0;
background-color: gold;
-webkit-transform: rotate(-90deg) translateX(100%);
-moz-transform: rotate(-90deg) translateX(100%);
-o-transform: rotate(-90deg) translateX(100%);
-ms-transform: rotate(-90deg) translateX(100%);
transform: rotate(-90deg) translateX(100%);
-webkit-transform-origin: 100% 100%;
-moz-transform-origin: 100% 100%;
-ms-transform-origin: 100% 100%;
-o-transform-origin: 100% 100%;
transform-origin: 100% 100%;
}
<div class="container">
<div class="info">
hello this is a sentence
</div>
</div>
Okay, so here's how I've done it!
http://jsfiddle.net/03r7gabp/2/
CSS
.info {
position: absolute;
bottom: 0;
left: 0;
background-color: lime;
transform: rotate(-90deg);
transform-origin: bottom left;
margin-left: 100%;
width: 200px; /* height of container */
}
The only bodge that I'm not happy with is the width having to be a fixed value (equal to the height of the container).
Breakdown
Step 1
Not much to see here, move along!
Step 2
Note that we've specified the origin of rotation to be the bottom left. Imagine you stick a pin in that corner of the <div> and you then spin it about this point.
Step 3
In the previous image our <div> was sat on the outside of the container. We can now adjust its margin to make it appear on the other side. Remember that the percentage specified is a measure of the width of the parent element
Step 4
Now we "bump" the item to the bottom of the container.
Step 5
Finally we have to give our div a width equal to the height of the parent container
An alternative solution would be to set the container to have overflow: hidden; and then put the width of the child element to arbitrarily large. Obviously if the length of sentence exceeded the height of the container, the words would be clipped (e.g. http://jsfiddle.net/03r7gabp/6/)
One solution is to change transform-origin: bottom left; to right and also change frombottom: 0 to top: 35px
.container {
width: 300px;
height: 200px;
border: 1px solid red;
position: relative;
}
.info {
position: absolute;
top: 35px;
right: 0;
-webkit-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
-o-transform: rotate(-90deg);
-ms-transform: rotate(-90deg);
transform: rotate(-90deg);
transform-origin: bottom right;
}
<div class="container">
<div class="info">
hello this is a sentence
</div>
</div>
Related
When working with hero images or full screen anything, I typically see text or images with the following bit of CSS:
.item {
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
What is this code actually doing?
The reason why transform: translate(-50%, -50%) is required is because you want the center of the element to line up with the center of its parent. In simple terms, it can be boiled down to translateX(-50%) translateY(-50%), which means:
move me leftwards by 50% of my width, along the x-axis, and
move me upwards by 50% of my height, along the y-axis
This effectively moves the center of the element to its original top left corner. Remember then when you set left: 50%; top 50% on the element, you are moving its top left corner to the center of its parent (which means it is not visually centered at all). By moving the element back leftwards and upwards by half of its width and height respectively, you are sure that its center now aligns with the parent's center, making it visually horizontally + vertically centered.
As a proof of concept, see the code snippet below: hover over the parent to cause the child element's "ghost" to reposition itself by means of transform: translate(-50%, -50%):
body {
margin: 0;
padding: p;
}
.parent {
background-color: #ccc;
width: 100vw;
height: 100vh;
position: relative;
}
.child {
background-color: rgba(0,0,255,0.5);
width: 50px;
height: 50px;
position: absolute;
top: 50%;
left: 50%;
}
.child::before {
background-color: rgba(255, 0, 0, 0.5);
position: absolute;
top: 0;
left: 0;
width: 50px;
height: 50px;
content: '';
transition: all .5s ease-in-out;
}
body:hover .child::before {
transform: translate(-50%, -50%);
}
<div class="parent">
<div class="child"></div>
</div>
TL;DR version
Let's say there is a .container and an .item inside.
This code below is positioning .item relatively to .container; meaning .item top left corner is in the center of its container
.item {
top: 50%;
left: 50%;
}
While the below is positioning .item relatively to its own width and height; meaning minus 50% of its width and height.
.item {
transform: translate(-50%, -50%);
}
If the two code snippets below are combined, then the expected center will show up.
When working with hero images or full screen anything, I typically see text or images with the following bit of CSS:
.item {
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
What is this code actually doing?
The reason why transform: translate(-50%, -50%) is required is because you want the center of the element to line up with the center of its parent. In simple terms, it can be boiled down to translateX(-50%) translateY(-50%), which means:
move me leftwards by 50% of my width, along the x-axis, and
move me upwards by 50% of my height, along the y-axis
This effectively moves the center of the element to its original top left corner. Remember then when you set left: 50%; top 50% on the element, you are moving its top left corner to the center of its parent (which means it is not visually centered at all). By moving the element back leftwards and upwards by half of its width and height respectively, you are sure that its center now aligns with the parent's center, making it visually horizontally + vertically centered.
As a proof of concept, see the code snippet below: hover over the parent to cause the child element's "ghost" to reposition itself by means of transform: translate(-50%, -50%):
body {
margin: 0;
padding: p;
}
.parent {
background-color: #ccc;
width: 100vw;
height: 100vh;
position: relative;
}
.child {
background-color: rgba(0,0,255,0.5);
width: 50px;
height: 50px;
position: absolute;
top: 50%;
left: 50%;
}
.child::before {
background-color: rgba(255, 0, 0, 0.5);
position: absolute;
top: 0;
left: 0;
width: 50px;
height: 50px;
content: '';
transition: all .5s ease-in-out;
}
body:hover .child::before {
transform: translate(-50%, -50%);
}
<div class="parent">
<div class="child"></div>
</div>
TL;DR version
Let's say there is a .container and an .item inside.
This code below is positioning .item relatively to .container; meaning .item top left corner is in the center of its container
.item {
top: 50%;
left: 50%;
}
While the below is positioning .item relatively to its own width and height; meaning minus 50% of its width and height.
.item {
transform: translate(-50%, -50%);
}
If the two code snippets below are combined, then the expected center will show up.
I have the following jsfiddle:
https://jsfiddle.net/quacu0hv/
I cant figure out how to center this div. The fact that it is rotated makes it hard to actually center the object on screen. How exactly can this be achieved with pure css? I imagine its due to the point of origin that changed its position (upper left vertex of the div).
div {
transform: rotate(-45deg) scale(2) translate(-50%, -50%);
opacity: 1 !important;
top: 50%;
left: 50%;
width: 200px;
height: 200px;
background: black;
position: absolute;
}
Try rearranging the transform values and see what happens ;)
Turns out order does matter. If you think about it, it does makes sense:
Rotate > Scale > Translate
Once you've rotated it, the origin has been rotated too. That's why your square moves "left" and "up" from the origin.
Translate > Rotate > Scale
This is what you want to do. Position before you make any other adjustments that can affect the origin.
Use CSS transform-origin: 50% 50% or try 0 0. Remove position: absolute first.
This is at 0 0
This is at 50% 50%
This is at 45% -290% Centered?
Yeah, looks centered to me, see Full Page. Anyways, as you can see from the other answers transform-origin is the best solution. Scott suggested to remove the transform: -50% -50% which makes perfect sense if you wanted the div centered in the first place, but if you wanted that in there still and have it centered as a square in a rectangle (height is smaller than width), then 45% by -290%.
SNIPPET
.box {
position: relative;
}
.center {
transform: rotate(-45deg) scale(2) translate(-50%, -50%);
transform-origin: 45% -290%;
opacity: 1 !important;
width: 200px;
height: 200px;
background: black;
position: absolute;
}
<div class='box'>
<div class='center'></div>
</div>
You could just remove translate(50%, 50%);
div {
transform: rotate(-45deg) scale(2);
opacity: 1 !important;
top: 50%;
left: 50%;
width: 50px;
height: 50px;
background: black;
position: absolute;
}
<div></div>
Fiddle
or add transform-origin: 0 0; to start transformations in the upper left corner.
div {
transform: rotate(-45deg) scale(2) translate(-50%, -50%);
transform-origin: 0 0;
opacity: 1 !important;
top: 50%;
left: 50%;
width: 50px;
height: 50px;
background: black;
position: absolute;
}
<div></div>
Fiddle
Using transform-origin you can get the result, also scale and rotate goes before positioning.
div {
transform-origin: 0 0;
transform: rotate(-45deg) scale(2) translate(-50%, 50%);
opacity: 1 !important;
width: 100px;
height: 100px;
background: black;
}
<div></div>
jsfiddle: https://jsfiddle.net/quacu0hv/8/
Here is my Fiddle : http://jsfiddle.net/4wd6vmjL/
I want to mask a div to show my image skew . but i dont want image to skew.
now there is a gap in mask and image can't fill all mask .
.mask{
background-image: url('http://www.birds.com/wp-content/uploads/home/bird4.jpg');
height:200px;
-webkit-transform: skew(-16deg);
-moz-transform: skew(16deg);
-o-transform: skew(16deg);
transform: skew(16deg);
}
Any advice ? Thanks
You need to change your css of .mask class.
.wrapper{
display: block;
height:200px;
background: #f8f8f8 none repeat scroll 0 0;
text-align: left;
-webkit-transform: skew(-16deg);
-moz-transform: skew(-16deg);
-o-transform: skew(-16deg);
transform: skew(-16deg);
border-right:medium none;
margin-bottom: 26px;
margin-left: 44px;
overflow: hidden;
z-index: 100;
width:300px;
}
.mask {
background-image: url("http://www.birds.com/wp-content/uploads/home/bird4.jpg");
background-position: center top;
height: 480px;
transform: skew(16deg);
width: 430px;
padding-left: 70px;
}
<div class="wrapper">
<div class="mask">asdassadd</div>
</div>
Just add the image inside another div and counterskew it with the exact opposite. The hardest bit is positioning your div now, which would take some tweaking - depending on the angle your inside div needs to be bigger. I have also positioned it at the center of the wrapping div.
.mask {
position: relative;
left: 100px;
width: 200px;
height:200px;
overflow: hidden;
-webkit-transform: skew(-16deg);
-moz-transform: skew(-16deg);
-ms-transform: skew(-16deg);
transform: skew(-16deg);
}
.mask > * {
position: absolute;
left: 50%;
top: 50%;
width: 370px;
height:370px;
color: #fff;
background-image: url('http://www.birds.com/wp-content/uploads/home/bird4.jpg');
-webkit-transform: skew(16deg) translate(-50%,-50%);
-moz-transform: skew(16deg) translate(-50%,-50%);
-ms-transform: skew(16deg) translate(-50%,-50%);
transform: skew(16deg) translate(-50%,-50%);
}
<div class="mask"><div>This is just text to show your skew is now undone. This is just text to show your skew is now undone. This is just text to show your skew is now undone.This is just text to show your skew is now undone. This is just text to show your skew is now undone. This is just text to show your skew is now undone. This is just text to show your skew is now undone. This is just text to show your skew is now undone.This is just text to show your skew is now undone. This is just text to show your skew is now undone. This is just text to show your skew is now undone.</div></div>
I have a main div (the red div in the fiddle) that has a smaller vertical tab on the side (the blue div in the fiddle).
The RED div is standard BUT the Blue div is rotated through 90 degrees (as I need to have vertical text in it). This is where the problems starts.
The red div is vertically positioned at 50% so it is in the middle of the page and locked with scrolling etc.
I want to align the blue div so that the top edge of the blue div is at the same Y position as the top edge of the red div.
I would prefer NOT to use jQuery but can do if required.
Desired output :
Fiddle is here : http://jsfiddle.net/kBKf6/
Here is the code I am using :
<div id="main" style="position: fixed; top: 50%; margin-top: -250px; left:0; height: 500px; width: 450px; background-color:red;">
Main Content Div
</div>
<div id="vertical_div" style="overflow:hidden; position: fixed; left:350px; height:40px; width:200px; margin: auto; background-color:blue; text-align:center; color:white; -webkit-transform: rotate(90deg) translate(-50%, -50%); -moz-transform: rotate(90deg) translate(-50%, -50%); -ms-transform: rotate(90deg) translate(-50%, -50%); -o-transform: rotate(90deg) translate(-50%, -50%); transform: rotate(90deg) translate(-50%, -50%);">
Side Tab
</div>
You don't need JS to align the rotated div. You can define a transform origin in CSS then, it becomes easy to align.
Side note : You can remove the -moz- and -o- vendor prefixes see caniuse
DEMO
HTML :
<div id="main">Main Content Div
<div id="verticaldiv">Side Tab</div>
</div>
CSS :
#main {
position: fixed;
top: 50%;
margin-top: -250px;
left:0;
height: 500px;
width: 450px;
background-color:red;
}
#verticaldiv {
overflow:hidden;
position: absolute;
left:100%;
bottom:100%;
height:40px;
width:200px;
background-color:blue;
text-align:center;
color:white;
-webkit-transform: rotate(90deg);
-ms-transform: rotate(90deg);
transform: rotate(90deg);
-ms-transform-origin:0 100%;
-webkit-transform-origin: 0 100%;
transform-origin: 0 100%;
}
You can also do it without relying on hardcoded sizes that move your div into position, but you need a wrapper around your .verticaldiv
demo:
http://jsfiddle.net/MCr6f/
demo 2:
http://jsfiddle.net/9LtKw/ (to show that different sizes don't matter)
html:
<div class="one">
Hello
<div class="pivot">
<div class="two">
Pretty!
</div>
</div>
</div>
css:
.one {
background: red;
position: relative;
float: left;
/*strange and difficult sizes*/
font-size: 3.237827em;
padding: 10px;
}
.pivot {
position: absolute;
top: 0;
right: 0;
-webkit-transform: rotate(90deg);
-moz-transform: rotate(90deg);
transform: rotate(90deg);
width: 0px;
height: 0px;
}
.two {
background: blue;
color: white;
position: absolute;
left: 0;
bottom: 0;
/*strange and difficult sizes*/
font-size: 12px;
padding: 0.3em;
}