Preserving div ratio when height is the limiting factor - javascript

I am trying to create a "slide" div that is centered in the middle of the screen with a constant aspect ratio.
Combining this trick for centering and this one for the ratio, I came up with this:
HTML
<div class="slide">
<div class="slide-content">
Percentage sized and still centered.
</div>
</div>
CSS
/* slide centered in the middle of the screen + width = 80% */
.slide {
position: fixed;
width: 80%;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background-color: red;
box-shadow: 0 0 30px rgba(0, 0, 0, 0.2);
}
/* aspect ratio of 2:1 */
.slide:before{
content: "";
display: block;
padding-top: 50%;
}
/* stretch the content to the slide size */
.slide > .slide-content {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
padding: 40px 60px;
transition: all 0.6s ease-in-out;
}
Fiddle is here: https://jsfiddle.net/3jph853w/
It works beautifully, expect on mobile in landscape view: the trick being based on width, the div is not resized properly and part of it "overflows" outside the screen. You can see it when you resize the fiddle output vertically.
How can I fix it ? I would rather keep it css only, with additional html markup is necessary. I am open to JS, but my project is Angular based and does not use jQuery.

This might be a start
Fiddle demo 100% of viewport
Fiddle demo 80% of viewport
html, body{
margin: 0;
}
.slide{
position: absolute;
width: calc(100vh * 2);
height: calc(100vw * 0.5);
max-width: 100vw;
max-height: 100vh;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.slide-content{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: red;
padding: 40px 60px;
box-sizing: border-box;
transition: all 0.6s ease-in-out;
}
<div class="slide">
<div class="slide-content">
Percentage sized and still centered.
</div>
</div>

add text-align:center; to the bottom of .slide > .slide-content {

Related

How can I centre a div dynamically to where my page is and make the page 'disabled' when the div shows? [duplicate]

This question already has answers here:
How to center a "position: absolute" element
(31 answers)
Closed 2 years ago.
I'm trying to do that when a button is pressed, it will display a div in the middle of the page no matter where my page is, it can be on the bottom part or top part of the page and still it would be in the middle.
I'm using position: absolute because I need it to be 'floating' above other elements.
I searched everywhere and didn't see how to do it. Only in the middle, but not 'dynamically'.
Also, how can I make the rest of the page that is behind the div disabled?
my current css:
#buyComponentTesting{
background-color: blue;
z-index: 99;
width: 200px;
height: 200px;
position: absolute;
top: 26%;
left: 40%;
}
As already suggested, it should be position:fixed instead of position:absolute. Please avoid other CSS written for demo.
.page{
pointer-events:none;//page disabled
/*Not required for this solution*/
width:100%;
height:100%;
/*Not required for this solution*/
}
#buyComponentTesting{
position:fixed;
width:100px;
height:100px;
top:calc(50% - 50px);
left:calc(50% - 50px);
pointer-events:all; /*but the div is accessible*/
/*Not required for this solution*/
display:inline-flex;
align-items:center;
justify-content:center;
border:1px solid transparent;
background:beige;
cursor:pointer;
/*Not required for this solution*/
}
#buyComponentTesting:hover{
border-color:#333;
}
<div class="page">
<div id="buyComponentTesting">The DIV</div>
</div>
#buyComponentTesting{
background-color: blue;
z-index: 99;
width: 200px;
height: 200px;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%);
}
The code above will center the div. top and left will move the upper right corner of the div to the center of the page but to actually have the div sit in the center we would need to move if left by its width / 2 and up by its height / 2 which is done with transform property.
Also you cloud center the div horizontally use left: 50%; transform: translateX(-50%);
Note: Code above has position: fixed to have the div appear even when scrolling.
To have the rest of the page "disabled" as You mentioned, one option would be to create an overlay with fixed or absolute position which will sit above all element except for the div. You can either use ::before selector or separate element to create overlay
div::before, .overlay{
content: ""; //Add this property only when using ::before or ::after, otherwise they won't be displayed
position: fixed;
top: 0;
left: 0;
z-index: 80; /*Less then z-index of the div*/
background-color: rgba(0, 0, 0, 0.7);
width: 100%;
height: 100%;
}
#buyComponentTesting{
background-color: blue;
z-index: 999;
width: 200px;
height: 200px;
position: relative;
margin : auto;
transform: translate(-50%, -50%);
}
Please try the above code share your feedback
Use position: fixed; instead of position: absolute;.
From below code, this is will be show in the middle.
#buyComponentTesting {
background-color: blue;
z-index: 999;
width: 200px;
height: 200px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
But If you want to create like popup than use this
.container {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 999;
background: rgba(0, 0, 0, 0.3);
}
#buyComponentTesting {
background-color: blue;
width: 200px;
height: 200px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
<div class="container">
<div id="buyComponentTesting">
</div>
</div>
I think, it will be helpful for you.

How to center vertically an absolutely positioned scaled element?

Without scale code works fine, but I need to center vertically an already scaled element. I am looking for solution using CSS or JS approaches.
Also I can not use transform-origin CSS property because it's unsupported in some browsers that I need to support...
https://jsfiddle.net/o62ja9r6/17/
.container {
position: fixed;
border: 2px dashed blue;
width: 400px;
height: 300px;
}
.slide {
position: absolute;
width: 76px;
height: 169px;
background-color: red;
}
.vertical-center {
top: 50%;
transform: scale(0.4) translateY(-50%);
/* transform: translateY(-50%); // <--- it works */
}
<div class="container">
<div class="slide vertical-center">
</div>
</div>
Order matters, swap translateY with scale.
.container {
position: fixed;
border: 2px dashed blue;
width: 400px;
height: 300px;
}
.slide {
position: absolute;
width: 76px;
height: 169px;
background-color: red;
}
.vertical-center {
position: relative;
top: 50%;
transform: translateY(-50%) scale(0.4);
}
<div class="container">
<div class="slide vertical-center">
</div>
</div>
Quick Explination
If you have an element that is 100px tall and you translate it along the y-axis by -50% it will move up 50% of it's height, which would be 50px. If you scale that 100px tall element first, down to 40% of it's height, then it will be 40px tall when you try to translate it along the y-axis, which will only move it up 20px.
Instead of translate you can use simple CSS for this
.vertical-center {
top: 0;
left:0px;
bottom:0px;
right:0px;
margin: auto;
transform: scale(0.4);
}
for working demo click here

Modal fixed position content shift

After a lot of research, I am unable to find a proper solution for the shifting to the right of fixed positioned elements, cover images, and standard content, when a modal window is open.
Note: I am looking for a general, clean solution, not an hardcoded fix that would work just on a specific layout.
Does anyone know how to fix this issue? Please refer to this example: http://codepen.io/microcipcip/pen/kXdRWK
body {
height: 2500px;
&.-modal-open {
overflow: hidden;
}
}
.fixed {
position: fixed;
top: 0;
left: 0;
width: 100%;
padding: 20px 0;
background: #FF0000;
}
.modal {
overflow-x: hidden;
overflow-y: scroll;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.4);
opacity: 0;
transition: opacity .2s ease-in-out;
body.-modal-open & {
opacity: 1;
}
}
The solution is very simple and a pure css fix:
.-modal-open .fixed,
.-modal-open .content {
overflow-y:scroll;
}
..however, this requires that your content is styled differently. You should never use a margin for your content, but rather wrap it in a container and use padding instead.
The scrollbar's width isn't always 17px... 17px is for Firefox, but 15px for chrome, sometimes IE doesn't even have a scrollbar width depending on the code.
Here is the updated pen:
http://codepen.io/scooterlord/pen/KgKLwB
edit: forgot to say, that this is a cross-browser solution and works flawlessly everywhere I tested it. If the browser is mobile, then no change of width happens anyway from the addition/removal of the extra scrollbars and depending on the browser the newly created scrollbars for the content/fixed elements is always the same as the initial body scrollbar.
The main trick is to not use body as your content wrapper. Use a dedicated div as wrapper and place your modals outside so the scrollbars don't interfere with each other.
var $btnShow = document.querySelector('.show');
var $btnHide = document.querySelector('.hide');
var $body = document.querySelector('.modal');
$btnShow.addEventListener('click', function() {
$body.classList.toggle('-modal-open')
});
$btnHide.addEventListener('click', function() {
$body.classList.toggle('-modal-open')
});
.wrapper {
position: fixed;
top: 0;
left: 0;
bottom:0;
right:0;
overflow: auto;
}
.content {
background: url('https://www.dropbox.com/s/m16kxhb2jg5jwwh/bear-800x450.jpg?dl=0&raw=1');
background-size: cover;
background-position: center center;
height: 2500px;
width: 100%;
}
.clickme {
position: fixed;
top: 50%;
left: 50%;
padding: 10px;
border: none;
background: #000000;
color: #ffffff;
text-transform: uppercase;
transform: translate(-50%, -50%);
}
.clickme:hover {
background: grey;
cursor:pointer
}
.modal {
overflow-x: hidden;
overflow-y: scroll;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.4);
display: none;
transition: opacity .2s ease-in-out;
z-index: 3;
}
.modal.-modal-open {
display:block;
}
.modal-content {
min-height: 1500px;
margin: 100px;
background: url('https://www.dropbox.com/s/u520y7yo711uaxi/poster2.jpg?dl=0&raw=1');
background-size: cover;
}
<div class="modal">
<div class="modal-content">Content
<button class="clickme hide">Toggle Modal HIDE!</button>
</div>
</div>
<div class="wrapper">
<div class="content">
<button class="clickme show">Toggle Modal SHOW!</button>
</div>
</div>
How about adding 17px right-margin to the body each time a modal is opened. That would emulate the space that was reserved for the scroll bar. (17px is the width of standard browser width)
body.-modal-open {
margin-right: 17px;
}
meanwhile, for for fixed element you recalculate the width;
.-modal-open .fixed {
width: calc(100% - 17px);
}
There is still one problem though, the CSS background image is still shifted, the solution is simply placing it in a div container instead of the body.

CSS Scaled Div Centring

I am having an issue centring a <div id='divTwo'> inside another <div id='divOne'>. This is normal an easy thing to do, however in this instance i have transform: scale(); with transform-origin: 50% 50% 0px; applied on 'divTwo'
#divOne {
top: 0px;
left: 0px;
width: 100%;
height: 100%;
}
#divTwo {
width: 1024px;
height: 768px;
margin: auto;
position: absolute;
top: 0; left: 0; bottom: 0; right: 0;
border-left: 131px solid #333333;
border-right: 131px solid #333333;
border-top: 47.5px solid #333333;
border-bottom: 47.5px solid #333333;
border-radius: 55px;
}
if the scale applied to the transform and the window is larger than the outerWidth(), 'divTwo' has no issue centring. However when the 'divTwo' is scaled and the window is smaller or equal to the outerWidth(). The div will no longer centre, instead it will place its centre point to be right side of the browser, resulting if half the of 'divTwo' being off the right hand-side of the browser. Changing transform-origin: 50% 50% 0px; to transform-origin: 0% 50% 0px; works so long as you don't scale vertically, and vice versa.
jsfiddle example : https://jsfiddle.net/yvyz49zp/
Thank you. I feel like am missing something of obvious.
I knocked this up relatively quickly in jsfiddle - no javascript needed. Just play around with the values until you get something you like.
Code:
body {
background: lightblue;
}
#container {
display: inline-block;
position: absolute;
width: 50%;
right: 50%;
top: 50%;
transform: translate(50%, -50%);
}
#dummy {
margin-top: 75%; /* Using the dummy is the trick - it locks the aspect ratio (at 4:3 in this case) */
}
#device {
position: absolute;
top: 10%;
bottom: 10%;
left: 0;
right: 0;
background-color: #333;
border-radius: 10%;
}
#screen {
position: absolute;
width: 70%;
height: 80%;
background: #0f0;
right: 50%;
top: 50%;
transform: translate(50%, -50%);
}
<div id="container">
<div id="dummy"></div>
<div id="device">
<div id="screen"></div>
</div>
</div>

Position fixed doesn't work inside relative position, CSS

I'm trying to put div with position:fixed inside div with position:relative.
This is CSS:
#wrapper {
background-color: #199eaf;
height: auto;
left: 0;
min-height: 100%;
position: relative;
text-align: left;
top: 0;
width: 100%;
}
.menu-space {
background: #fff none repeat scroll 0 0;
height: 174px;
left: 0;
overflow: hidden;
padding: 43px;
position: fixed;
top: 0;
transform: skewY(-10deg);
width: calc(100% + 100px);
z-index: 800;
}
This for some reason doesn't work as I expect. My div goes inside next div in #wrapper div (See screenshot: http://www.awesomescreenshot.com/image/445294/fb3d41bfb92a0f76d60266ed0ac4f0a9) I can make this work just if I use one of this two solution for .menu-space div
transform: skewY(-10deg) translate(0px, -101px);
or
top: -170px;
But I really don't want to use those minus values. Can someone please help me to find better solution?
This is how menu should look
http://www.awesomescreenshot.com/image/445297/e799ee584ead6007b9fe16628ccc15bc
and on scroll:
http://www.awesomescreenshot.com/image/445300/cee6600490bab7e58a479da23ac9974a
Thank you!
By default, transforms happen from the center of the element. Your skew is twisting the element from its center, causing the left side to drop and the right side to rise.
Set transform-origin: top left (or 0 0 if you prefer) and you can get rid of the negative top or translate.
.menu-space {
background: #fff none repeat scroll 0 0;
height: 174px;
left: 0;
overflow: hidden;
padding: 43px;
position: fixed;
top: 0;
transform: skewY(-10deg);
transform-origin: top left;
width: calc(100% + 100px);
z-index: 800;
}
See MDN
The reason for this is the transform: skewY(-10deg);. As per the W3C spec, if position: fixed; is used on an element inside an element with a transformation applied to it, the fixed-position element is positioned relative to that transformed element.

Categories