CSS rotate transform - left and top issue - javascript

I have a parent div on which I am applying a rotation transform of -90 deg. Inside the div, one of the child should not transform, I tried transform:none and all its variants but nothing worked and it gets transformed anyways. So, I had to apply a reverse rotation on the child element to set it horizontal.
Now the problem which occurs is that changing the left of child on which reverse rotation was applied actually changes its top and changing top changes its left when altered using Firebug. So the child element is displayed at a wrong position.
if(self._sOrientation == "vertical"){
self.RotatePH($thisComp.closest('.ComponentFrame'),"-90deg");
if(self.isIE==false){
self.RotatePH($thisComp.find('.revertTransform'),"90deg");
// $thisComp.find('.revertTransform').css('-moz-transform', 'none');
}
Actually the component is too complex to provide any usable code on stack overflow
Edit:
I believe the second rotation should be about the axis of the main component instead of rotating about itself. Is it possible to change axis of rotation?
The child has position:fixed; if that matters

I've created a Fiddle to better understand your problem, and i think it's not something related to transformation axis.
More simply, when you alter top, or left position of the child element, it moves correctly referring to it's parent and then the transformation take place.
The child div alter it's position refering to parent div and inheriting it's transformations.
So the final effect that you see is that the object is altering it's left position when you tweak the top and viceversa, but in fact it's not.
Child div seems to moved top and left, but in fact it's not.
I suggest you to change your approach if it's applicable in your situation, and create a fake_parent element that is a child instead (you can see that in the fiddle).
//INSTEAD OF THIS APPROACH
<div class="parent">PARENT DIV
<div class="child">CHILD DIV</div>
</div>
//USE THIS APPROACH
<div class="fake_child">CHILD DIV
<div class="fake_parent">PARENT DIV</div>
</div>
CSS
.parent {
width:100px;
margin:3em;
padding:2em;
transform:rotate(45deg);
-ms-transform:rotate(45deg);
/* IE 9 */
-webkit-transform:rotate(45deg);
background-color:rgb(0, 112, 255);
}
.child {
background-color: #fff;
position: absolute;
padding:1em;
transform:rotate(-45deg);
-ms-transform:rotate(-45deg);
-webkit-transform:rotate(-45deg);
}
.fake_child{
width: 100px;
background-color: #fff;
padding: 1em;
margin: 3em;
position: relative;
}
.fake_parent{
position:absolute;
width:100%;
height:200%;
background-color: rgb(0,121,255);
top:0;
left: 0;
transform:rotate(45deg);
-ms-transform:rotate(45deg);
/* IE 9 */
-webkit-transform:rotate(45deg);
z-index: -1;
}
body {
background-color: #ccc;
font-family: Arial, sans-serif;
}

can't you use transform-origin (http://css-tricks.com/almanac/properties/t/transform-origin/):
-webkit-transform-origin: center center;
-moz-transform-origin: center center;
-o-transform-origin: center center;
transform-origin: center center;

I believe the second rotation should be about the axis of the main component instead of rotating about itself. Is it possible to change axis of rotation?
Yes, if you know the width of the parent (or the ratio of the child's width to the parent's width, I believe). You can use transform-origin to have the child rotate back to its original position by setting transform-origin: hpw hpw, where hpw is half the width of the parent.
If we only rotated the parent and the child was at (0,0) relative to the parent, the child would end up in the bottom left corner of the parent. Imagine a box with its width and height both set to the width of the parent, and positioned at (0,0) relative to the rotated parent. (It follows that the child is in the bottom left corner of this box.) It should be clear that rotating this box will put the child back to it's original position and rotation.
The top and left of the child will still be relative to the rotated parent, so you'll have to position the child with left: your_top * -1 and top: your_left.
Demo: http://jsfiddle.net/HTCwL/1/
Edit: Here's an animated version of the demo to make things clearer http://jsfiddle.net/HTCwL/2/
Relevant CSS:
#parent {
width: 150px;
height: 300px;
border: 1px solid blue;
position: relative;
top: 10px; left: 150px;
-webkit-transform: rotate(-90deg);
}
#child {
position: absolute;
width: 100px;
height: 100px;
left: -10px;
top: 150px;
border: 1px solid red;
-webkit-transform: rotate(90deg);
-webkit-transform-origin: 75px 75px;
}
Edit: Yes, the child having position fixed matters. From https://developer.mozilla.org/en-US/docs/Web/CSS/transform,
If the property has a value different than none [...] the object will act as a containing block for position: fixed elements that it contains.
The containing block for fixed elements is normally the html element (see http://www.w3.org/wiki/CSS_absolute_and_fixed_positioning#Containing_blocks) but when the parent of a fixed element has a transform set it becomes their containing block. I'm not aware of any way to avoid that.

Related

How can I stretch an absolute div to the width of it's grandparent while inside an absolute parent div

My html/css is structured like this:
<div class="grandparent">
<div class="row">...</div>
<div class="absolute-parent">
<div class="absolute-child">...</div>
</div>
</div>
.grandparent {
position: relative;
}
.absolute-parent {
width: *gets set by JS*
height: 30px;
position: absolute;
top: 0;
bottom: 0;
left: *gets set by JS*
overflow: hidden;
margin: 0 auto;
transition: all 0.5s ease-in-out;
}
.absolute-child{
align-items: center;
display: flex;
flex-direction: row;
justify-content: center;
bottom: 0;
position: absolute;
top: 0;
left: *gets set by JS*
margin: auto 0;
transition: left 0.5s ease-in-out;
}
.absolute-parent has a fixed height while width and left position get set by javascript depending on the position of a selected element in .row div, it serves as window to absolute-child's content which should be layered with .row-div" content.
Right now .absolute-child only stretches as wide as the content inside of it, I'd like to make it stretch the whole container width of .grandparent div so .absolute-child and .row are right on top of one another.
Cheers !
The only way I can think of, is making the parent div inherit the with of the grand-parent, and making the child inherit the width of the parent. But, the grand parent needs to have a set width for that. Or just setting manually the width of all those divs. It may not be the answer you are expecting, but that is the method I have been using in such situations for a long time.
Since an absolutely positioned element refers to its next higher relatively positioned ancestor for its position and size (if defined in percentage), it should work to simply add width: 100% to .absolute-child to make it as wide as the .grandparent element

CSS to position image a percentage of another image

Say I have an image that has width
width: 100vw;
Is it possible to position a title say 50% of the way down from this image? I can't think of how to do it as the height will be changing based on the vw, so can this be done with CSS only, or do I need Javascript? Either way, how would I do this?
Thanks
Edit: I have tried the various suggestions below but it seems that whenever I try to use solely CSS with position:relative it messes up the rest of my code. Is there a javascript function, therefore, that can calculate the height of the image as a % of the page height, and then can I position my title at say 75% of the height of the image?
I'm not entirely sure if I've understood you correctly or not, but if you want to vertically centre a piece of text over the top of a responsive image, you could do this:
div {
position: relative;
}
img {
width: 100vw;
height: auto;
}
p {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
margin: 0;
}
<div>
<img src="https://unsplash.it/200/100/?random">
<p>SOME TEXT</p>
</div>
https://jsfiddle.net/fjh6msqL/
Sure, add a parent around the image and set it to inline-block so that it will match the width of the image, add position: relative so that you can absolutely position your title text in relation to the parent, and then either add an element with your title text or use a pseudo element from the parent (that's what I did in this example) and absolutely position that 50% from the top, and use translateY(-50%) to move the image back up 50% of it's own height so it's in the middle of the image vertically. Here is a good article on how to center stuff using CSS https://www.w3.org/Style/Examples/007/center.en.html
div {
display: inline-block;
position: relative;
}
div:after {
content: 'here is your title';
color: white;
background: black;
position: absolute;
top: 50%;
width: 100%;
text-align: center;
}
img {
width: 100vw;
}
<div class="parent">
<img src="http://kenwheeler.github.io/slick/img/fonz1.png">
</div>
You can't really do that with an image without using some Javascript. The best solution I think would be to use a div element and set it's background-image property to the image you want to display, and then position your title vertically inside the div. Something like this:
<div style="background: url('url-to-image') no-repeat; background-size: cover; background-position: center center;">
<h2 class="title"></h2>
</div>
Vertical positioning can be tricky, but there are ways, for example:
CSS Vertical align middle
With CSS margin:auto , max-height:0 with absolute position actually does the magic. this will center your title text perfectly regardless of screen size. Instead of giving title a width and height we can set top, left, right, bottom property to 0 which actually scale the element to its relative parent's size. Hope this helps.
body{
margin:0;
padding:0;
}
.img-placeholder{
position:relative;
}
.img-placeholder img{
width:100vw;
height:auto;
}
.img-placeholder h2{
position:absolute;
margin:auto;
top:0;
right:0;
bottom:0;
left:0;
max-height:0px;
text-align:center;
}
<div class="img-placeholder">
<img src="http://lorempixel.com/output/sports-q-c-640-480-2.jpg">
<h2>Image Title</h2>
</div>

move object relative to screen and not to parent transforms

I have two objects - parent and child
the parent has some angle , for example: 90 degrees
the child doesn't have angle, but it's also rotated because it's linked to it's parent transforms.
now I need to move the child 100px in the x Axis and -200px in the y Axis ,
but because the parent has angle, the child moved in the wrong directions.
actually, it is the right directions relative to the parent transforms, but I need to move the child relative to the screen.
I need help with the math...
html
<div id="parent">
<div id="child"></div>
</div>
style
#parent {
background: red;
position: absolute;
left: 0px;
top: 0px;
width: 150px;
height: 250px;
-webkit-transform-origin: 75px 200px;
-webkit-transform: translate(300px,160px) rotate(90deg);
}
#child {
background: green;
position: absolute;
left: 0px;
top: 0px;
width: 90px;
height: 120px;
-webkit-transform-origin: 90px 20px;
-webkit-transform: translate(100px,-200px);
}
thanks
As you have seen rotating an element rotates the frame of reference for the element.
In the above diagram the purple axes are the frame of reference for the red rectangle and the green child after a rotation theta clockwise.
You want to move the green rectangle relative to the screen (blue axes), ie translate using the orange vectors.
Given the wanted translation (x,y) relative to screen axes you need to find the translation (xtranslate,ytranslate) relative to the purple axes.
Using the formulas in the diagram with x=100, y=-200 gives xtranslate=-200, ytranslate=-100
Note also that since translate is a move from current position by an amount transforming the origin makes no difference.
So code for child becomes
#child {
background: green;
position: absolute;
left: 0px;
top: 0px;
width: 90px;
height: 120px;
-webkit-transform: translate(-200px,-100px);
}

Absolutely position element based on center

A convenient way to make an absolutely-positioned hovering element that lets height vary with content using Javascript is to specify the width, top and left as style fields. For instance:
popup.style.width = foo.offsetWidth - 10 + 'px';
popup.style.top = document.getElementById(bar)
.getBoundingClientRect().top + 'px'; // for IE7, can't use offsetTop
popup.style.left = '15px';
How can I adapt this code to absolutely position the popup based on its center, rather than its top? I'd like to do popup.style.center instead of popup.style.top, but that's not how CSS works. A completely naive solution is to add it to the DOM, then measure its height, and subtract half the height from the top.
Alternatively, is there a completely different approach that would still allow setting an arbitrary position for each corner of the element?
I'm looking for a pure Javascript solution (e.g. no jquery).
Important: I'm not trying to center the popup inside another element. Rather, I want the center point of the popup to be specified as a pixel offset from the top of the screen. This pixel offset may be based on another element, or it may be a raw number.
In your important note you are dealing with two different notions:
The first one, offset from the top of the screen, can be achieved with position:fixed.
The second one, offset based on another element, is where absolute positioning is useful, and will be relative to the first position:relative parent element.
As suggest Table-Cell centering (thanks to Itay comment) it makes sense in your case to use table display because it's exactly its purpose: adapt the container to its content.
You need some extra html:
<div class="container">
<div class="popup">
<div class="content">
<!-- CONTENT -->
</div>
</div>
</div>
And apply this css:
.container {
position: absolute; /* or fixed */
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.popup {
display: table;
height: 100%;
}
.content {
display: table-cell;
vertical-align: middle;
}
Thanks to the table-cell display you can use vertical-align: middle, no more need of javascript.
For horizontal centering you can still add a classic width: 50%; margin: 0 auto; on popup class.
To do this in jquery would be pretty simple
DEMO jsFiddle
jQuery.fn.center = function(parent) {
if (parent) {
parent = this.parent();
} else {
parent = window;
}
this.css({
"position": "absolute",
"top": ((($(parent).height() - this.outerHeight()) / 2) + $(parent).scrollTop() + "px"),
"left": ((($(parent).width() - this.outerWidth()) / 2) + $(parent).scrollLeft() + "px")
});
return this;
}
$("div.target").center(true);
I had been thinking about this for a while. You can actually absolute position an element from the center of a container instead of the corners by adding a div inside the container. This inner container, or reference container, is 50% height and 50% width of the parent container. Then you can position relative to the bottom right corner.
HTML
<div class="container">
<div class="container-inner">
<div class="pointer pointer-1" data-name="pointer-1"></div>
<div class="pointer pointer-2" data-name="pointer-2"></div>
</div>
</div>
CSS
This is the container we want to place pointers in
html, body {
height: 100%;
}
.container {
height: 80%;
width: 80%;
margin: 0 auto;
border: 1px solid blue;
}
We use this container to get a center point that we can use as a reference. We use the bottom right corner of this div as our reference point.
.container-inner {
border: 1px dashed red;
height: 50%;
width: 50%;
position: relative;
}
Create a couple of targets 60px in diameter
.pointer {
height: 40px;
width: 40px;
background-color: orange;
border: 10px solid red;
border-radius: 60px;
position: absolute;
}
Center target one in the center of the container
.pointer-1 {
bottom: calc(-0% - 30px);
right: calc(-0% - 30px);
}
Position target 2 25% right and down from the container center.
.pointer-2 {
bottom: calc(-50% - 30px);
right: calc(-50% - 30px);
}
You can see a working demo of this JSBin.
Would this work?
.popup {
margin-top: -50%;
}
In the end, I decided to just add the element to the DOM, measure its height, and subtract half the height from the top. I make the element invisible before adding it, and visible again after adjusting the height, to avoid flickering.

Fixed Text on a Parallax Website

I have created this site and am trying to implement fixed text on the first slide (the one with the Nike basketball). Currently, I have the text 'The first of its kind' as part of the background image. Is it possible to separate it from the background and place the text in its own div?
I am stumped for ideas as the first slide is created by using three separate div - one for the top portion of the ball, the second for the bottom portion of the ball, and the third as the magnification of the ball. I thought of attaching the text within the first and second div, but it causes the text to scroll with the page as oppose to fixing it in place.
Site link: http://www.sfu.ca/~jca41/stuph/parallaxTest/parallax03/parallax03.html
Yes, use position:fixed with left and top css attributes.
e.g.
#fixedText {
position:fixed;
left:100px;
top:50px;
}
EDIT:
To accommodate the overlapping of slides, you would have to apply a z-index to the slides and the text.
For instance you could give the page class a z-index of 2 (and position:relative or the z-index doesn't take effect), the #fixedText rule a z-index of 1, and the #first rule a z-index of 0. This would create the layering you are after:
#fixedText {
position: fixed;
left: 75px;
top: 120px;
font-size: 35pt;
color: white;
z-index: 1;
font-family: helvetica;
}
#first {
background: url(images/01.jpg) no-repeat fixed;
height: 1000px;
z-index: 0;
}
.page {
margin: 0;
padding: 0;
overflow: auto;
width: 100%;
z-index: 1;
position: relative;
}

Categories