Pure CSS: centering vertically and horizontally an absolute positioned element with width depending on children - html

So... I got this code: https://jsfiddle.net/jmg63s3e/1/
The code actually works fine if you resize the browser window until you have the text inline with the image and that's what I'm trying to achieve, but if you resize it down eventually the text drops below the image even if the wrapper width is a lot smaller than the window width.
My only purpose is to have:
the whole wrapper centered both vertically and horizontally in the browser window. Its total width and height unknown, depending on its children
row1 and row2 must not be inline: row2 must be below row1
All the elements inside row1 (the image and the text containing 2 spans) must be inline with each other
And well, the spinner inside row2 must also be centered inside the row but that was never a problem whatever solution I tried
As a matter of fact the only dynamic element in the whole code is the first span which in the example contains Player #1, since it should be the name of the player and it can be anything, any length.
Of course if I wanna make it responsive I will have to use media queries or dynamically change widths and heights and font-sizes with JS, and I'm willing to do so. My problem here is only the wrapper itself and the text that drops below the image even if the wrapper width is a lot smaller than the window width, so I'm asking for a solution that works as long as the wrapper width is smaller than the window width. When the wrapper width drops below the window width, I will handle the style with responsive media queries or JS. I would just like to have the wrapper to be centered both vertically and horizontally in the window, and its size to be dynamic and depending on children.
I've already tried any solution I could think of, but with an unknown wrapper width I just can't figure it out. Can someone help me please? I'm open to any suggestion and any solution, as long as it's pure CSS and it doesn't involve JS. Thanks everyone in advance

You can use flexbox to fix these problems.
Here's an updated fiddle with old CSS commented out: https://jsfiddle.net/jmg63s3e/3/
First, to align the wrapper both horizontally and vertically you need to make the parent container a flex container with display: flex and use justify-content: center and align-items: center. You also need to set a height or else it will wrap to the height of the child and not give you the centering effect. I used the following. The height can be whatever you need it to be.
.trump-waiting {
display: flex;
justify-content: center;
align-items: center;
font-size: 0;
overflow: hidden;
height: 100vh;
}
Next, I used display: flex on the wrapper and flex-direction: column to make sure they are all lined up like we want them to be.
.trump-waiting .wrapper {
display:flex;
flex-direction:column;
To fix row1, again I used flexbox and removed the inline-block and the set height. You could set the height as long as you take care of resizing the font in the text divs, with media queries for instance. Otherwise, with an explicit height, the font at the size it's at now will break out of their containers. Without explicitly setting the height, the containers will adjust in size.
.trump-waiting .row1 {
display: flex;
flex-direction: row;
/* display: inline-block; */
/* height: 60px; */
background-color: yellow;
}
I also added flex-shrink:0 to .image to keep it from shrinking on resize.
To keep Player #1 and 'is choosing the trump suit' inline, I also added display: flex and flex-direction: row to .row keep them on the same line.
Finally, to align the loader, I did the vertical/horizontal alignment trick used above, plus added some padding to the div to give it some space and removed the old css.
.trump-waiting .row2 {
display: flex;
justify-content: center;
align-items: center;
padding: 16px 0 16px 0;
/* display: block; */
/* margin-top: 50px; */
The last step would be to use media queries to adjust the font-sizes on .text spans so the font doesn't expand their container on resize.
Many ways to skin a cat and I'm sure others will have different perhaps better solutions, but hope this helps. There's a great summary of flexbox here if you need it. I may have left out a change in this summary, but it should all be in the fiddle.
EDIT: Realized I made a mistake summarizing the css in the jsfiddle and also removed a redundant css property. Now updated.

Related

Container with align-items: center is moving when an item switch its height but ONLY when the container isn't fully visible on the page

I have a div in display: flex which contains another div with some text content and a ul. The items are aligned vertically with align-items: center. When i hover an item in the list, the content changes and every text has a different size.
But here it is, everything looks fine when all the container is visible on the page but if I scroll down until the top of the container is out of the viewport then the container starts to expand or reduce. It can be seen when it switches to a content with more or less lines than the previous one.
I made this GIF for a better understanding of the problem : https://gifyu.com/image/STtIP
And I recreated the bug here : https://codepen.io/lorenzofg/pen/JjLxJBj
I could fix the height of the content div but I would like to avoid that and keep a dynamic height to properly center the text.
Does someone know what's going on or can tell me if what i wanna do is possible or not?
replace height: 100%; with min-height:100vh; in the container class.
remove width or replace width: 20%; with width: 50%; in the content class.

Flex image won't shrink with screen size when container is a hyperlink

Can someone let me know if this is an undocumented bug with flexbox, or that I'm just doing it wrong? I've got 3 images lined up in a row inside a div container. This is as simple as it gets folks.
Without any hyperlinks, all 3 images shrink down perfectly as they should.
<div style="width: 100%; margin: 0 auto; display: flex; justify-content: center;">
<img src="flash-tooltip.png">
<img src="html-tooltip.png">
<img src="portables-tooltip.png">
</div>
Now, only 2 out of the 3 images when viewed on all devices shrink down correctly depending on manually maximizing dragging the browser, of via viewport.
The only image that will not change shape or size is the image with the hyperlink. So, I took the hyperlink off the first image. And decided to test it by placing it on the 2nd, now the 1st image and the 3rd image shrinks fine.
But, the 2nd image stays the exact same size? Tried then adding hyperlinks to all the images and none of them change to match the screen width?
Am I wrong to say flex items if they are images won't flex if they have a hyperlink lol? Surely this cannot be the case right?
The problem has nothing to do with hyperlinks. You could wrap the image in any element (try a span or a div) and it will have the same effect as the a container.
The problem is the hierarchical structure of a flex container.
When you set an element to display: flex (or inline-flex) you establish a flex container.
Only the children of a flex container are flex items. Descendants of a flex container beyond the children are not flex items and don't accept flex properties.
Here are the three flex items:
<img src="flash-tooltip.png">
<img src="html-tooltip.png">
<img src="portables-tooltip.png">
The img in the first element is not a flex item. It is wrapped by the a element and is therefore a child of a flex item.
The two img items can shrink because of two default settings on a flex container:
flex-wrap: nowrap ~ flex items are forced to remain on a single line
flex-shrink: 1 ~ flex items are permitted to shrink to prevent them from overflowing the container
If you switch to flex-wrap: wrap and/or flex-shrink: 0 the img items will no longer shrink.
The a item does not shrink because of another default setting: min-width: auto, which means that flex items cannot be smaller than the size of their content. In this case, the a item cannot shrink below the width of the image.
You can override this setting by adding min-width: 0 to your code.
#container {
display: flex;
}
span {
min-width: 0;
display: flex;
}
img {
min-width: 0;
}
<div id="container">
<span><img src="http://i.imgur.com/60PVLis.png"></span>
<img src="http://i.imgur.com/60PVLis.png">
<img src="http://i.imgur.com/60PVLis.png">
</div>
More information:
Why don't flex items shrink past content size?
Proper use of flex properties when nesting flex containers
I don't know why, but this solves the problem. I would like to know why as I cannot find out any information about this issue in any HTML/CSS documents.
If you add the following.
<style>
img {
max-width: 100%;
height: auto;
}
</style>
Then all 3 images will shink perfectly. Even if they have hyperlinks. Funny enough if you set just the width: 100%; then the image with the hyperlink stays the exact same size as the image is, and all the others without hyperlinks blow up to the 100% size of the container.
I didn't know flexbox had such rules that needed you to set image max-widths to make items responsive/shrink down if they have a hyperlink attached.
So, tried it in chrome: Only the image now with the anchor shrinks down, the other 2 stay the same size. FireFox all 3 shrink down, but chrome only shrinks the image with the hyperlink wrapped around it.
Tried wrapping hyperlinks around each of the other 2 images and in chrome, they all shrink down fine.
Can someone explain what is going on? How can i set a max-width: and height: auto on a hyperlink?
It's tough to say without seeing your CSS, but you probably are not selecting the images within <a> tags. If you alter your CSS to select images that are inside of <a> tags, it should work fine.
I've added my complete working solution. Thanks to many people here giving their various methods. So, this is for anyone else who may be struggling.
First lets set the style's up.
<style>
img {
max-width: 100%;
width: 100%;
min-width: 0;
min-height: 0;
}
</style>
adding min-width: 0; | min-height: 0; seems to be overkill, but with chrome, it works much better apparently than setting them as auto;
Since it's using flexbox we don't add the usual width: 33.33%; even if there are 3 images. In flexbox, this will just space them out way to far apart within a 100% wide div.
Here's the really important part I found out the hard way.
You must use either width: 100% on the images, or max-width: 100%; otherwise, (On Chrome without adding either 100% width or max-width: 100%; it just won't flex/shrink down when you minimize the browser to test its responsiveness.)
So, next to keep each of the 3 images in perfect aspect ratio remember to include each image inside its own div container. Otherwise, they will shrink but will just skew up to each other as they do.
As you can see the first image is even wrapped in a hyperlink, but because it's inside its own div it will shrink and grow completely flush and inline with the other images. This saves using extra markup and saves adding a span tag then making that a flex container to contain the hyperlink. I've tried both ways this is by far the easier method.
I've used inline styles for the flexbox container. (bad habit.)
<div style="border: 2px solid red; margin: 0 auto; display: flex; justify-content: center;">
<div>
<img src="flash-tooltip.png">
</div>
<div>
<img src="html-tooltip.png">
</div>
<div>
<img src="portables-tooltip.png">
</div>
</div>
Remember to close off that last /div it's a real gotcha!
And that's how I've done it. Tested it in many browsers works perfectly. Even on mobile phones and tablets.
If you don't like flexbox? You can do the same thing using regular floats.
I've included this same method as above, only this time in a float: version.

How can I do this with CSS and HTML?

It's hard to explain, but I'll try. I am trying to create a grid of divs that will never go off the page horizontally. Hence, the bottom scroll bar will never show. Instead, divs that are pushed off the window will wrap to the next row. There may not be as many divs on the bottom row as there are on the previous. In this case, the divs on the bottom row must be centered in the window. As the window resizes, the margins between the divs should expand or shrink to equalize the space between them. If the window resizes enough, the number of columns should change to fit the divs. Hopefully this image will help:
float:left and display:inline-block are close, but they don't resize margins and are not centered. I would like this to be done with pure CSS and HTML, but I do know JavaScript if it is necessary.
You can achieve this by using flexbox
Demo
The key parts are:
.grid {
display: flex;
flex-wrap: wrap;
justify-content: space-around
}
.grid > div {
flex-basis: 300px;
}

Footer not aligning below main content in flexbox

I'm using flexbox to responsively lay out a bunch of images.
.cards
.card.card1
.card.card2
.card.card3
.card.card4
etc....
footer
css:
.cards{
display: flex;
width: 100%;
flex-wrap: wrap;
height: 81.2rem;
}
.card{
display: flex;
flex-wrap: wrap;
height: 100%;
max-height: 28rem;
position: relative;
}
The problem I'm having is...
I have a footer that needs to be below the .cards div, but since .cards has a height, the footer is hovering over the div where I tell the height to be. (The cards themselves extend past the height.)
I have tried setting a taller height, however, then the space between the rows of cards expand (which I don't want). I've also tried not setting a height, but then the cards don't lay out at all, they just disappear or float way down the page.
Is there a way I can clear the .cards div?
Or just in general, get the footer to appear below the cards?
This shows the footer where it currently is, which is incorrect.
This shows the footer where I need it to be:
Instead of height: 100%, which limits the container to a fixed height, use min-height: 100% or remove height altogether.
If your height property is installed properly, you may need to apply the min-height to parent or ancestor elements.
More details: Working with the CSS height property and percentage values
Additional notes from OP:
Add the height to the direct children of the flex-box, this allows the container to determine its height.
On another note, if you put the height on the sub-children (not direct descendants), the container flex-box will not know how to set its own size and will have no height.

Using 'table' and 'table-cell' with display property in responsive design?

I am using display: table; on the container and display: table-cell; on the child elements, to highlight some posts horizontally on a page.
The thing is, I have no idea as to how to make them responsive, i.e. as the screen-size becomes smaller, each child (i.e. table-cell) should become proportionately smaller, whilst continuing to stay aligned horizontally.
How do I do this?
Example Code: http://www.codepen.io/anon/pen/dCLgq
Demo: http://codepen.io/anon/full/dCLgq
To scale the inner containers down with the page, you can set the container div's width to 100%:
in your example:
#the-big-stories {
display: table;
table-layout: fixed;
/** add 100% width **/
width:100%;
}
further, if you want to scale the images with the child containers, just give them width: 100%; as well with height:auto;
see your codepen forked below:
http://codepen.io/braican/pen/xCmsw
You'll probably need to use media queries to really get the stuff inside to play nicely together, but the container will scale with the browser, as will the inner div's.