Compensate for the area moved by transform: translate - html

I'm trying to remove the empty area an element leaves behind after it has been moved via transform: translateY. So basically on that code snipped below I want the yellow element to be right below the blue element without the space in between. Because it's for a template I need to achieve this without changing the code of the above or below element.
The element is moved with the percentage of the size of the element. My initial idea was to add
margin-bottom: -50%;
but the 50% are calculated with the width of the element and not the height. Another idea was to make the position absolute. But that doesn't work either since I don't know how big the content of the elements will be.
Do you have any idea how to achieve this with just css?
div {
padding: 50px;
}
.wrapper {
background-color: green;
position: absolute;
width: 500px;
height: 500px;
}
.above {
background-color: red;
}
.moved {
background-color: blue;
transform: translateY(-50%);
}
.below {
background-color: yellow;
}
<div class="wrapper">
<div class="above">
</div>
<div class="moved">
</div>
<div class="below">
</div>
</div>
EDIT:
Just to be a bit more precise:
The divs represent independent sections of my template. Since these are reusable components I can not edit the other sections (below and above). Therefor I'm looking for a solution in which the moved section just uses as much space as it does after the translation.

Since you defined the height of each one of these divs to be 100px, and translated the blue one for 50% of it = 50px, you can add a margin-bottom: -50px; and be all set

Try adding a translateY(-50%) as well on your yellow element, this will moved it upwards to remove the space between it and the blue.
.below {
background-color: yellow;
transform: translateY(-50px);
}

Related

How to achieve this sticking out image layout without using negative margins?

This is the layout image:
As you can see in the image, the images of the phones are sticking out of the blue container.
I have tried several things, such as:
I tried to use a grid with 5 rows where a <div> tag expanded all the rows and was set to have its background as the phone images. Then I set the blue background box to use only the rows form 2-4.
This somehow did the trick, but when the browser window was resized the image started to shrink and be positioned in a funky way.
As a newcomer to CSS I want to avoid negative margins because I have read they are "evil".
Is there any way to accomplish this in a clean/non-hacky way?
You can use the transform property to move the images where they need to be.
You'll need to build your layout as usual, but without the images being raised/lowered outside their default position.
Once you've done that, you can use transform: translateY(-100px) to raise or lower the images into their target position.
A quick example of this can be shown using <div> tags:
/* Setup some basic layouts to mimic the layout required */
.container {
padding-top: 100px;
padding-bottom: 100px;
}
.banner {
height: 200px;
background: blue;
display: flex;
justify-content: center;
align-items: center;
}
.image-1 {
height: 200px;
width: 200px;
background: red;
transform: translateY(-50px); /* move the image up */
}
.image-2 {
height: 200px;
width: 200px;
background: green;
transform: translateY(50px); /* move the image down */
}
.example-filler {
}
<div class="container">
<div class="banner">
<div class="image-1"></div>
<div class="image-2"></div>
<div class="example-filler">Lorem ipsum</div>
</div>
</div>
If you don't wan't to use negative margins (which are fine in this situation). You can try to give these styles to your image.
img {
position: relative;
top: -100px;
}
You can learn more about the "position" property here.
It is very important for beginners to understand how it works.

position: absolute not doing what I expect

I am having problems getting the grasp of position: absolute
I understand that it positions itself according to the position of its relative parent. So what is wrong with my example? when clicking on the first ".col-lg-6", why is the faded blue line not centered on the right col?
Please could you rework the code and explain why this is happening?
.formWrapper
{
background: blue;
height: 100vh;
position: relative;
margin: 0;
}
.formWrapper .contactForm
{
width: 750px;
height: 400px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: yellow;
}
<div class="formWrapper">
<div class="contactForm row">
<div class="col-lg-6"><h1>HI</h1></div>
<div class="col-lg-6"><h1>HI</h1></div>
</div>
</div>
I can't rework the code and give you what you want exactly, because I don't see the faded blue line you're talking about. But, I will explain what is going on with your code, as I see it.
HTML Markup
<div class="formWrapper">
<div class="contactForm row">
<div class="col-lg-6"><h1>HI</h1></div>
<div class="col-lg-6"><h1>HI</h1></div>
</div>
</div>
.formWrapper
{
background: blue;
height: 100vh;
position: relative;
margin: 0;
}
You have a .formWrapper div colored blue. It takes up the full screen, and you've positioned it relative. Positioning it relative provides an anchor for its child element to use when defining its own position as absolute (necessary).
.formWrapper .contactForm
{
width: 750px;
height: 400px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: yellow;
}
You've defined the a fixed width and height of the yellow .contactForm div and colored it yellow.
By defining position: absolute, with top:50% and left:50%, the top left position of the .contactForm div would appear in the very middle of the .formWrapper div. However, you've also added the transform: translate(-50%, -50%) style, which moves the .contactForm div to the left 50% of its own width and up 50% of its own height.
Important
The position: absolute style that you've set in the parent of the div.col-lg-6 elements does not affect the children's positioning within that element. Position absolute only directly affects the actual element to which you've applied this style, changing its position in reference to its own parent, or the closest parent that has a position style defined.
Position Fixed
If your goal is to have a pop up that sits in the center of the screen, then you might want to use position: fixed, which positions the element relative to the window. This way you don't have to worry about the effects of other elements.
You could position the popup in the middle of the view the same way you positioned the .contactForm div in the middle of the its parent div.
Bootstrap
If you are using bootstrap or any other css framework, you may want to consult their documentation on how to accomplish your goals. Frequently, when using a css framework, adding your own custom styles that affect the sizes and positioning of elements can have consequences that are difficult to manage.
By setting a position of absolute or fixed, you might break the expected flow of the rest of the css. So, only do it when there is no standard way of doing what you need and you know the consequences.

Container transformed to fit, positioned absolute, still causing overflow as if not transformed

Edit: I had forgot to mention that I also had it positioned absolute. Absolutely sorry for that. Edits in content are in bold.
I have this container that I use for scaling its contents. I needed to scale things down evenly, and realized that I could use transform CSS attribute for my convenience.
The result is good, the contents are scaled and placed nicely. The problem is, I get overflow on the body element, caused by the container element. It is not crossing the window borders, not when its transformed, and is positioned absolute. However, for some reason, my browser (Edge 16) decides to accommodate space for the element as if it was not transformed.
.container {
position: absolute;
width: 10000px; height: 10000px;
border: solid 100px red;
transform-origin: top left;
transform: scale(0.01);
}
.orange-box {
width: 5000px; height: 2000px;
background-color: orange;
}
<div class='container'>
<div class='orange-box'>
</div>
I have tried it a couple of times on Chrome 64, I don't get overflows on body there. I do want to make use of this, though, and I want to have Edge support.
Is there a way to get around of this bug/issue? Is there, perhaps, a way to prevent specific elements from causing overflow, without completely hiding them? I don't want to overflow: none on the body, either, since the body might legitimately be overflowing.
I don't think it's a bug in Edge. At least, I see scrollbars in Chrome.
May be you can get around it placing the div far to the left and top (that don't stretch the body boundaries)
.container {
width: 10000px;
height: 10000px;
border: solid 100px red;
transform: scale(0.01);
top: -10095px;
position: absolute;
left: -10095px;
transform-origin: right bottom;
}
.orange-box {
width: 5000px; height: 2000px;
background-color: orange;
}
<div class='container'>
<div class='orange-box'>
</div>
I encapsulated it all inside another container, positioned it as relative, transformed it with translate(0). Transformation does nothing, but it is different than none, which is all I need to have a child positioned as fixed to respect its container's position: See MDN/position/fixed
Then, I have changed the positioning of our former container to fixed, which did what the absolute couldn't do on Edge 16, and removed the container from the document flow.
.container-container {
position: relative;
top: 50px;
transform: translate(0);
}
.container {
position: fixed;
width: 10000px; height: 10000px;
border: solid 100px red;
transform-origin: top left;
transform: scale(0.01);
}
.orange-box {
width: 5000px; height: 2000px;
background-color: orange;
}
<div class='container-container'>
<div class='container'>
<div class='orange-box'>
</div>
</div>
I positioned the container-container away from the top left, to show that the fixed child moves along with it, thanks to the translate(0) transform.
However, I didn't use this. I instead styled the container-container to have its overflow as hidden via CSS, and left everything as before. This works out only if the container-container has width and height set to be contained within the body, which was already the case in my application.

Cropping an image diagonally with CSS and adding a border

I am trying to achieve an effect where I can diagonally crop an image in a way that is displayed below. I am aware of clip path as a solution but it would not be suitable in this scenario since it is not supported by certain browsers which are essential for this particular task. (IE and Edge)
Additionally, the cropped edge would need a black border which adds on to the complexity of what I am trying to do. Having searched for answers and coming up with anything, any suggestions would be appreciated.
Maybe you could overlay the image with a rotated element (div or something) that you give a border and white background. This solution would work if you're okay with a solid background color.
Another solution, depending on your requirements, could be to simpy use a .png image with transparency.
Yes you can, it's a bit tricky to get the sizes of the divs correct. But here's generally how to do it:
HTML:
<div id="outerwrapper">
<div id="innerwrapper">
<div id="content">
<span>asdf</span>
</div>
</div>
</div>
CSS:
#content {
width: 100px;
height: 100px;
background-color: red;
transform: rotate(-60deg);
transform-origin: 50% 50%;
position: relative;
}
#content span {
position: relative;
top: 30px;
left: 30px;
}
#innerwrapper {
border-right: solid 3px black;
overflow: hidden;
width: 100px;
height: 100px;
}
#outerwrapper {
transform: rotate(60deg);
transform-origin: 50% 50%;
width: 120px;
height: 120px;
overflow: hidden;
}
Fiddle:
https://jsfiddle.net/ywfpeve8/
To explain this:
You have a div that contains the content itself. In this example it's just a span, but it can be anything. (I put it in to see that in the end everything is horizontal again)
You rotate that content div to some degree that suits you.
You place that div in a wrapper with a different size where you can position your content in. That div has an overflow: hidden, to crop all that content that is outside of the inner wrapper box. That wrapper then also has the border where you want the crop to be highlighted.
That inner wrapper is placed in an outside wrapper that rotates the same amount at the content div, but backwards, leaving you with the original 0 degree alignment of the content. This div again has overflow: hidden to crop that inner wrapper again so that you can hide the other "crop edges" that you want to be invisible. In my example code I didn't to the correct dimensions and positionings as it takes a bit to get right. But if you have an image with a white background, that shouldn't be very hard anymore to get things right.
Bonus: the background of the top-level element (that element that holds the outerwrapper can have any background at all and you won't see a rectangular box at the bottom right corner (for this example) as everything just happens with overflow: hidden and without bars that go over the content to hide it :)

How can I dynamically offset the position of a child element to 50% of it's own size?

Exactly as the title says, I have an element that dynamically resizes itself to fit the content. I would like this element to be positioned proportionally to its size (so it stays centered on a fixed point). The problem I'm facing is that the parent element I'm using to position the child element is not inheriting the calculated size of the child element. I don't know if there's any CSS tricks to make the parent element get it's child's height without having to specify it using javascript.
The following fiddle demonstrates the problem, with the issue being displayed on the left and the desired final product on the right (minus the ability to do it dynamically).
http://jsfiddle.net/YEcx6/
The html:
<div class="parent">
<div class="child">This content is dynamic</div>
</div>
<div id="static" class="parent">
<div class="child">This content is static</div>
</div>
and the CSS:
.child {
position: relative;
right: -50%;
top: -50%;
}
.parent {
position: absolute;
top: 50px;
left: 10px;
background: #ddd;
}
#static {
left: 100px;
height: 54px;
}
.child {
background: red;
max-width: 50px;
}
== EDIT ==
I now know there is no way to do any relational positioning with regard to height without using javascript.
What about height:auto and width:auto on the parent ?
The problem is in order to get the vertical positioning to work right, you need to have a defined height to reference by. Since you want a dynamic height, it makes it challenging. I tried using negative margin-top instead of top but that, as I suspected, defaults to using the width of the element to determine the height offset (which does not achieve your effect). I found a solution that might work for you if you can compromise by setting the position of the upper left corner of the .child rather than the upper left corner of the .parent. Here is the solution, with the explanation following (this was only tested in FF).
HTML
<div class="parent">
<div class="child">This content is dynamic
<div class="bkg"></div>
</div>
</div>
CSS
.parent {
position: absolute;
top: 50px;
left: 10px;
}
.child {
position: relative;
}
.bkg{
position: absolute;
width: 100%;
height: 100%;
top: 50%;
bottom: -50%
left: -50%;
right: 50%;
background-color: #ddd;
z-index: -1;
}
The .parent now is supposed to be the final position of the upper left of where .child will be. The .child contains the content you want but gives a relative position by which .bkg will be related. By giving .bkg a width and height of 100%, that set's its size, which apparent is enough to correctly then calculate the correct 50% offsets to reposition it down and to the left (which is the same relationship you wanted for your original look).