Why vertically centering needs a specified body height but not width? - css

I'm trying to vertically center a div using only display flex. I know how to do this with other methods, but need some insight on why this does not work. (The container do get horisontally centered but, not vertically)....
<body>
<div class="container"></div>
</body>
body {
box-sizing: border-box;
margin: 0;
padding: 0;
display: flex;
justify-content: center; //works fine
align-items: center; //
}
.container {
width: 80vw;
height: 80vh;
border-radius: 10%;
padding: 0;
margin: 0;
}

Yes, it gets centered, as you can see here:
body {
box-sizing: border-box;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
border: solid 1px green;
}
.container {
width: 80vw;
height: 80vh;
border-radius: 10%;
padding: 0;
margin: 0;
border: solid 1px red;
}
<div class="container"></div>
But probably what you want is this
body {
box-sizing: border-box;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
border: solid 1px green;
height: 100%;
}
html {
height: 100%;
}
.container {
width: 80vw;
height: 80vh;
border-radius: 10%;
padding: 0;
margin: 0;
border: solid 1px red;
}
<div class="container"></div>

Related

how to make nested div with CSS only

Given the follow html and css, how to make the nested box like the
.parent {
width: 200px;
height: 200px;
border: 1px solid blue;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: center;
}
<div class='parent'></div>
draw them using background:
.parent {
width: 200px;
height: 200px;
border: 1px solid blue;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: center;
background:
/* color position / width height*/
linear-gradient(red 0 0) left 20px top 20px/50px 50px,
linear-gradient(green 0 0) right 30px top 20px/50px 50px,
linear-gradient(blue 0 0) left 40px bottom 40px/50px 50px;
background-repeat:no-repeat;
}
<div class='parent'></div>
You can use the before or after pseudo element in CSS to achieve what you're looking for without altering the HTML at all. Take a look:
.parent {
width: 200px;
height: 200px;
border: 1px solid blue;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: center;
}
.parent::before {
content: "";
width: 100px;
height: 100px;
background-color: black;
display: flex;
align-items: center;
justify-content: center;
}
<div class='parent'></div>

Single column flex container with scaled-down images

I'm trying to style some HTML that appears in a flash card program that I use, and I feel pretty lost as to what I'm doing wrong. What I want is pretty simple (I think) and the use case struck me as ideal for flexbox, but perhaps my approach is wrong.
It's a single column of content. A primary image appears at the top of the column, while two secondary images appear side-by-side directly below the primary image. Some text appears below that.
The height of the outermost container is based on the browser height. As the browser area is reduced, the images to should scale down, but never up (beyond their nominal dimensions) if more browser area is available. The secondary images should scale down faster than the primary image; if there's limited space, more should go to the primary image. The secondary images do not usually share the same dimensions, so the bigger of the two images should begin shrinking before the smaller (i.e., only shrink when necessary). All aspect ratios should be maintained during scaling.
What I have so far (here's a fiddle) nearly does what I want, except that the secondary images won't scale down with browser height, while the primary image won't scale down with browser width. This is iteration 20 or 30 at this point, so apologies if there are a bunch of vestigial rules left behind. I could really use some help! Thanks!
EDIT: see below for a visualization of how I'd like the content to respond as browser height shrinks. Notice that 1) secondary images never exceed their yellow container 2) they only scale when they must (150x75 didn't have to scale at all since the adjacent image is tall) 3) the yellow container scales faster than the primary image and 4) all images maintain their aspect ratios.
Before Browser height reduction ---> After
body {
font-family: arial;
font-size: 26px;
text-align: center;
color: black;
background-color: white;
}
.smallhint {
font-size: 16px;
color: #8c8c8c;
}
img {
padding: 0;
margin: 0;
font-size: 0;
}
.flex-column {
display: flex;
flex-direction: column;
padding: 0px;
margin: 0px;
height: 90vh;
flex-grow: 0;
min-width: 0;
min-height: 0;
}
.flex-row {
display: flex;
flex-direction: row;
flex: 0 1.5 auto;
justify-content: center;
align-items: center;
padding: 0px;
margin: 0px;
font-size: 0;
min-width: 0;
min-height: 0;
background-color: yellow;
}
.context {
display: flex;
min-height: 0;
background-color: blue;
}
.content img {
height: 100%;
}
.primary {
position: relative;
z-index: 0;
right: 0;
bottom: 0;
padding: 0;
font-size: 0;
min-height: 0;
}
.primary img {
border-style: solid;
border-width: 3px;
border-color: black;
height: calc(100% - 2*3px);
}
.mobile .nightMode .primary img {
border-style: solid;
border-width: 3px;
border-color: black;
}
.mask {
position: absolute;
z-index: 1;
top: 0;
right: 0;
width: 100%;
height: 100%;
font-size: 0;
}
.nonimage {
padding-top: 5px;
display: inline;
}
<div class="container">
<div class="flex-column">
<div class="primary"><img src="https://via.placeholder.com/200">
<div class="mask"><img src="https://via.placeholder.com/200/FF000"></div>
</div>
<div class="flex-row"><img src="https://via.placeholder.com/75x150"><img src="https://via.placeholder.com/150x75">
</div>
<div class="nonimage">
<div class="smallhint">Some Text<br>Other Text</div></div>
</div>
</div>
</div>
I think this could be a possible solution, #img1 being the first of the secondary images:
img {
max-width: 100%;
}
#img1 {
height: 20vw;
max-height: 150px;
min-height: 75px;
}
.primary img {
height: 50vw;
max-height: 200px;
}
These rules address the question, although there are still some issues with this approach that could be of importance.
body {
font-family: arial;
font-size: 26px;
text-align: center;
color: black;
background-color: white;
}
.smallhint {
font-size: 16px;
color: #8c8c8c;
}
img {
padding: 0;
margin: 0;
font-size: 0;
display: block;
object-fit: scale-down;
min-height: 0;
}
.flex-column {
display: flex;
flex-direction: column;
padding: 0px;
margin: 0px;
height: 90vh;
flex-grow: 0;
min-width: 0;
min-height: 0;
}
.flex-row {
display: flex;
flex: 0 1.5 auto;
flex-direction: row;
justify-content: center;
align-items: center;
min-height: 0;
background-color: green;
}
.context {
display: flex;
flex-direction: column;
max-height: 100%;
background-color: blue;
}
.primary {
position: relative;
z-index: 0;
right: 0;
bottom: 0;
padding: 0;
font-size: 0;
min-height: 0;
align-items: end;
background-color: orange;
}
.primary img {
margin-left: auto;
margin-right: auto;
border-style: solid;
border-width: 3px;
border-color: black;
height: calc(100% - 2*3px);
}
.mask {
position: absolute;
z-index: 1;
top: 0;
right: 0;
width: 100%;
height: 100%;
font-size: 0;
}
.nonimage {
padding-top: 5px;
display: inline;
}

How to center object with CSS transform scale

I'm trying to implement a zoom in/out functionality, just like you would have on a document editor like google docs or any word processor application. The problem I'm having is that I cannot keep the "document" centered and also be able to scroll all of its parts into view. Here is a small demonstration of the problem: https://codepen.io/liviu_vasut/pen/dyGbwwO
document.getElementById('objectToScale').style.transform = "scale(3)";
.container {
display: flex;
align-items: center;
justify-content: center;
padding: 5px;
width: 300px;
height: 200px;
border: 1px solid #000000;
left: 0px;
top: 0px;
margin: 10px;
overflow: auto;
}
.object {
position: relative;
width: 120px;
height: 120px;
display: inline-block;
background-color: grey;
border-radius: 25px;
padding: 5px;
transform-origin: center;
transform: scale(1);
}
<div class="container">
<div id="objectToScale" class="object">x</div>
</div>
Thanks for your time.
You scale only some inner element inside the whole box, but expect see the whole box scaled. if you want to scale the white padding and all the inner content to stay visible (and be able to scroll to) you should add some wrapper inside with width: 100% and height: 100%, and scale it, so the whole content become scaled.
Also, as #HaoWu mentioned, you should set the transform-origin to 0 0.
The final product should look somewhat like this:
var scaled = false;
function toggleScale() {
var objects = document.getElementsByClassName('wrapper');
for (var i = 0; i < objects.length; i++) {
objects[i].style.transform = scaled ? 'scale(1)' : 'scale(3)';
}
scaled = !scaled;
}
.container {
width: 300px;
height: 200px;
border: 1px solid #000000;
left: 0px;
top: 0px;
margin: 10px;
overflow: auto;
}
.wrapper {
width: 100%;
height: 100%;
display: flex;
box-sizing: border-box;
align-items: center;
justify-content: center;
padding: 5px;
transform-origin: 0 0;
}
.object {
position: relative;
width: 120px;
height: 120px;
display: inline-block;
background-color: grey;
border-radius: 25px;
padding: 5px;
transform-origin: center;
transform: scale(1);
}
<input type="button" onclick="toggleScale()" value="Toggle Scale" />
<div class="container">
<div class="wrapper">
<div id="objectToScale" class="object">x</div>
</div>
</div>
Actually, use the transform-origin: 0 0; and manually set the scrollbar to the center:
var scaled = false;
function toggleScale() {
[...document.getElementsByClassName('object')].forEach(e => {
e.classList.toggle('scaled');
e.parentElement.scrollTop = (e.parentElement.scrollHeight - e.parentElement.clientHeight) / 2;
e.parentElement.scrollLeft = (e.parentElement.scrollWidth - e.parentElement.clientWidth) / 2;
});
}
* {
box-sizing: border-box;
}
.container {
display: flex;
align-items: center;
justify-content: center;
padding: 5px;
width: 300px;
height: 200px;
border: 1px solid #000000;
left: 0px;
top: 0px;
margin: 10px;
overflow: auto;
}
.object {
position: relative;
width: 120px;
height: 120px;
display: inline-block;
background-color: grey;
border-radius: 25px;
padding: 5px;
transform-origin: 0 0;
}
.scaled {
transform: scale(3);
}
<input type="button" onClick="toggleScale()" value="Toggle Scale" />
<div class="container">
<div class="object">cannot see the entire object when scaled</div>
</div>

Position with position absolute and translateY in displayFlex (DropDown item)

Hello I'm doing a popup menu signin and I'm trying to position my fontawesome icon in the same place as mine :: before
like this:
i want this:
but I got this:
code:
<div className="App">
<div className="a">A</div>
<div className="b">
<div className="icon">
<FontAwesomeIcon
className="adjust"
icon={faUser}
size="2x"
fixedWidth
color="red"
/>
</div>
<div className="popup" />
</div>
</div>
css:
.App {
width: 100%;
height: 100px;
background: red;
display: flex;
justify-content: space-between;
}
* {
margin: 0;
padding: 0;
}
.a {
display: flex;
align-items: center;
width: 100%;
height: 100%;
background: blue;
}
.b {
position: relative;
display: flex;
flex-direction: column;
width: 220px;
height: 100%;
background: green;
}
.icon {
width: 100%;
height: 100%;
display: flex;
background: yellow;
justify-content: flex-end;
align-items: center;
cursor: pointer;
}
.popup {
position: absolute;
transform: translateY(calc(50% + 15px));
width: 100%;
background: red;
height: 200px;
}
.popup::before {
content: "";
display: block;
position: absolute;
right: 20%;
top: -15px;
border-bottom: 15px solid #000;
border-left: 15px solid transparent;
border-right: 15px solid transparent;
}
example:
https://codesandbox.io/s/morning-architecture-oi51j
I'm trying to use display: flex and position absolute for this, but to no avail

How do I center a rectangular div inside another rectangular div

I'm trying to make a rectangular div that's 95% the width of the viewport and 20% high. But I want another rectangular div inside of that, that is vertically and horizontally centered with a slight2px margin.
.Outer {
border: 1px solid #ccc;
max-width: 95vw;
max-height: 20vh;
width: 95vw;
height: 20vh;
margin: auto;
display: block;
}
.Inner {
border: 1px solid hotpink;
width: 95%;
height: 95%;
margin: auto;
}
It depends upon requirements. But according to question, here is the answer. Please take a look and let me know in case of any issue
.Outer {
width: 95vw;
height: 20vh;
border: 1px solid #ccc;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.Inner {
border: 1px solid hotpink;
position: absolute;
top: 10px;
right: 10px;
bottom: 10px;
left: 10px;
}
<div class="Outer">
<div class="Inner"></div>
</div>
Tried to use relative measuring units just in case you are dealing with a responsive design. The .outer box is display: table and the Inner is display: table-cell. They sit perfectly together and the 2px margin your requested is provided by a 2px padding from .Outer
html {
box-sizing: border-box;
font: 500 16px/1.428'Consolas';
height: 100vh;
width: 100vw;
}
*,
*:before,
*:after {
box-sizing: inherit;
margin: 0;
padding: 0;
}
body {
position: relative;
font-size: 1rem;
line-height: 1;
height: 100%;
width: 100%;
}
.Outer {
position: absolute;
top: 20%;
left: 3%;
outline: 1px solid #ccc;
max-width: 95vw;
max-height: 20vh;
width: 95vw;
height: 20vh;
margin: auto;
display: table;
padding: 2px;
}
.Inner {
border: 1px solid hotpink;
width: 95%;
height: 95%;
margin: auto;
display: table-cell;
}
<section class="Outer">
<section class="Inner"></section>
</section>
I'm not 100% this is what your looking for because this has Magic Numbers, but here is a JSFiddle of what I came up with using your provided code.
#Outer {
border: 1px solid #ccc;
max-width: 95vw;
max-height: 20vh;
width: 95vw;
height: 20vh;
margin: auto;
display: block;
position: relative;
}
#Inner {
border: 1px solid hotpink;
width: 95%;
height: 50%;
position: aboslute;
margin-top: 5vh;
margin-left: 2.5vw;
}
<div id=Outer>
<div id=Inner>
</div>
</div>
JSFiddle
Hopefully this helps and you could mess around with it to use percentages on the viewpoints instead of magic numbers.
When I want to center a div vertically, I have a couple classes that help me to do it.
.outer {
border: 1px solid #ccc;
max-width: 95vw;
max-height: 20vh;
width: 95vw;
height: 20vh;
margin: auto;
display: block;
}
.inner {
border: 1px solid hotpink;
width: 95%;
height: 90%;
margin: auto;
}
.valign-wrap {
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.valign-wrap .valign {
display: block;
}
<div class="outer valign-wrap">
<div class="inner valign center"></div>
</div>
JSFiddle
I always recommend add these classes to your projects, they are very useful. Good luck!

Resources