Vertically and horizontally center a heading underneath an image - javascript

I have created the following jsfiddle on a website that I'm building.
The first heading has 3 lines, whilst the other 2 just have one line. I have added a min-height to my boxes so they are all equal.
I would now like to center the heading on the vertical and horizontal axis.
I have tried to achieve this with flexbox, but it's only aligning horizontally. What am I doing wrong here?
.container {
width: 600px;
max-width: 90%;
margin: 0 auto;
}
.third {
float: left;
width: 32%;
min-height: 227px;
margin: 0 2% 2% 0;
background: #fff;
}
.last {
margin: 0 0 2% 0;
}
header {
padding: 12px;
}
h2 {
margin: 0;
display: flex;
align-items: center;
justify-content: center;
}
img {
display: block;
height: auto;
max-width: 100%;
}
<div class="container">
<section class="third">
<img src="http://bit.ly/1OTNPkt" alt="Kitten">
<header>
<h2>Title one which is slightly longer goes here</h2>
</header>
</section>
<section class="third">
<img src="http://bit.ly/1OTNPkt" alt="Kitten">
<header>
<h2>Title two</h2>
</header>
</section>
<section class="third last">
<img src="http://bit.ly/1OTNPkt" alt="Kitten">
<header>
<h2>Title three</h2>
</header>
</section>
</div>
Update:
I'm looking for a solution that supports IE including 9.

I suggest to use nested flexbox, drop the float and min-height on the section. The flex layout is smart enough to get equal height automatically. For IE9 support, see the bottom part.
.container {
width: 600px;
max-width: 90%;
margin: 0 auto;
display: flex;
}
.third {
/* float: left; */
width: 32%;
/* min-height: 227px; */
margin: 0 2% 2% 0;
background: gold;
display: flex;
flex-direction: column;
}
.last {
margin: 0 0 2% 0;
}
header {
padding: 12px;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
h2 {
margin: 0;
}
img {
display: block;
height: auto;
max-width: 100%;
}
<div class="container">
<section class="third">
<img src="http://bit.ly/1OTNPkt" alt="Kitten">
<header>
<h2>Title one which is slightly longer goes here</h2>
</header>
</section>
<section class="third">
<img src="http://bit.ly/1OTNPkt" alt="Kitten">
<header>
<h2>Title two</h2>
</header>
</section>
<section class="third last">
<img src="http://bit.ly/1OTNPkt" alt="Kitten">
<header>
<h2>Title three</h2>
</header>
</section>
</div>
Edit: IE9 support. I would use some Javascript to do the equal height stuff, the following example using jQuery + CSS table cell to do the vertical center.
$(document).ready(function() {
var maxHeight = 0;
$("h2").each(function() {
if ($(this).height() > maxHeight) {
maxHeight = $(this).height();
}
});
$("h2").height(maxHeight);
});
.container {
width: 600px;
max-width: 90%;
margin: 0 auto;
}
.third {
float: left;
width: 32%;
/* min-height: 227px; */
margin: 0 2% 2% 0;
background: gold;
}
.last {
margin: 0 0 2% 0;
}
header {
padding: 12px;
}
h2 {
margin: 0;
display: table-cell;
vertical-align: middle;
}
img {
display: block;
height: auto;
max-width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="container">
<section class="third">
<img src="http://bit.ly/1OTNPkt" alt="Kitten">
<header>
<h2>Title one which is slightly longer goes here</h2>
</header>
</section>
<section class="third">
<img src="http://bit.ly/1OTNPkt" alt="Kitten">
<header>
<h2>Title two</h2>
</header>
</section>
<section class="third last">
<img src="http://bit.ly/1OTNPkt" alt="Kitten">
<header>
<h2>Title three</h2>
</header>
</section>
</div>

Tried using display: table and it sort of works but it turns out that you can't use percentages for border-spacing
Demo: https://jsfiddle.net/2dkycc1L/

I made the whole grid using flexbox to make them all equal height and removed the min-height. The header element is also flexing to make the title vertically align in the middle: https://jsfiddle.net/5yq37fha/.

Related

Row submenu appears in wrong place after click [duplicate]

This question already has answers here:
Position absolute but relative to parent
(5 answers)
Closed 2 years ago.
I have static top bar and left menu, and scrollable long content on right. In my (long) submenu I use position: absolute to not change row height. Submenu position for rows 2 and 3 in below snippet is wrong and non-intuitive and unwanted scroll bar appear. How to fix it?
body { margin: 0}
button { height: 20px}
.hide { display:none; }
.container { display: flex; }
.topBar { background: red; height: 30px; }
.side__menu {
height: calc(100vh - 30px);
background: yellow;
display: flex;
flex-direction: column;
justify-content: space-between;
width:100px;
}
.main__panel {
overflow: auto;
height: calc(100vh - 30px);
width: calc(100vw - 100px);
}
.row {
display: flex;
justify-content: space-between;
align-items: center;
height: 200px;
background: #ddd;
margin: 10px;
}
.submenu {
position: absolute;
right: 100px;
background: #fdd;
height: 70px;
}
<div class="topBar">Top Bar</div>
<div class="container">
<div class="side__menu">
<div>item1</div><div>item2</div><div>menu footer</div>
</div>
<div class="main__panel">
<div class="row">
Row 1
<button onclick="s1.classList.toggle('hide')">toggle submenu</button>
<div id="s1" class="submenu hide">submenu</div>
</div>
<div class="row">
Row 2
<button onclick="s2.classList.toggle('hide')">toggle submenu</button>
<div id="s2" class="submenu hide">submenu</div>
</div>
<div class="row">
Row 3
<button onclick="s3.classList.toggle('hide')">toggle submenu</button>
<div id="s3" class="submenu hide">submenu</div>
</div>
</div>
</div>
I make some investigation and discover that height: 100vh (with calc or not) "create problems" with submenu. I accidentally find one solution - just add following style to row class
position: relative;
But I totally don't know why it actually works - so feel free to create answer and explain it if you know why (or show some alternative approach)
body { margin: 0}
button { height: 20px}
.hide { display:none; }
.container { display: flex; }
.topBar { background: red; height: 30px; }
.side__menu {
height: calc(100vh - 30px);
background: yellow;
display: flex;
flex-direction: column;
justify-content: space-between;
width:100px;
}
.main__panel {
overflow: auto;
height: calc(100vh - 30px);
width: calc(100vw - 100px);
}
.row {
display: flex;
justify-content: space-between;
align-items: center;
height: 200px;
background: #ddd;
margin: 10px;
position: relative;
}
.submenu {
position: absolute;
right: 100px;
background: #fdd;
height: 70px;
}
<div class="topBar">Top Bar</div>
<div class="container">
<div class="side__menu">
<div>item1</div><div>item2</div><div>menu footer</div>
</div>
<div class="main__panel">
<div class="row">
Row 1
<button onclick="s1.classList.toggle('hide')">toggle submenu</button>
<div id="s1" class="submenu hide">submenu</div>
</div>
<div class="row">
Row 2
<button onclick="s2.classList.toggle('hide')">toggle submenu</button>
<div id="s2" class="submenu hide">submenu</div>
</div>
<div class="row">
Row 3
<button onclick="s3.classList.toggle('hide')">toggle submenu</button>
<div id="s3" class="submenu hide">submenu</div>
</div>
</div>
</div>
Tested on: Chrome, Safari and Firefox

Align text in the center by ignoring the absolutely positioned element

I am developing a flex table from scratch and the table supports filtering and sorting. The icons for filters and sorting are displayed in the table header (right corner). Also my table supports that the user can position the header text left/center;
My problem:
Since the icons are inside the table header, icons as well occupies some space. So when i position the elements in the center, i see the alignment gets disturbed as shown below.
body {
width: 100%;
}
.table-header, .table-body {
display: flex;
width: fit-content;
border: 1px solid black;
padding: 10px;
}
.header, .data {
display: flex;
min-width: 150px;
width: 150px;
border-right: 1px solid black;
display: flex;
justify-content: center;
position: relative;
}
.header .text {
width: 100%;
white-space: nowrap;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
}
.icons {
float: right;
right: 0;
display: flex;
}
<div class="table">
<div class="table-header">
<div class="header">
<div class="text">Hlkjklkjlkjlkj lkjlkjlkjlkjlkjljlkjlkj</div>
<div class="icons">
<span> &#9760</span>
<span> &#9760</span>
</div>
</div>
<div class="header">9747
<div class="text">Header 2</div>
<div class="icons">
<span>b</span>
<span>b</span>
</div>
</div>
<div class="header">
<div class="text">Header 3</div>
<div class="icons">
<span>a</span>
<span>b</span>
</div>
</div>
<div class="header">
<div class="text">Header 4</div>
<div class="icons">
<span>a</span>
<span>b</span>
</div>
</div>
</div>
<div class="table-body">
<div class="data">123</div>
<div class="data">123</div>
<div class="data">123</div>
<div class="data">123</div>
</div>
<div class="table-body">
<div class="data">123</div>
<div class="data">123</div>
<div class="data">123</div>
<div class="data">123</div>
</div><div class="table-body">
<div class="data">123</div>
<div class="data">123</div>
<div class="data">123</div>
<div class="data">123</div>
</div>
</div>
Code: Here
What i tried
So since the icons as well take some space, to avoid this i positioned them absolutely relative to the header. So the alignment problem got solved . But for long headers where ellipsis has to be shown, the ellipsis hides behind the icons as shown below
Code: Here
So what is the solution to this ? I want to maintain the center position by reducing the space occupied by the icons. Is it possible through CSS? Please help. Thanks :)
If you try to do that with absolute positioning you need to know what exact width your icons can take.
Then possible solution is to add padding rule (left/right) into table headers, so CSS code should be like this:
body {
width: 100%;
}
.table-header, .table-body {
display: flex;
width: fit-content;
border: 1px solid black;
padding: 10px;
}
.header, .data {
box-sizing: border-box;
padding: 0 30px;
display: flex;
min-width: 150px;
width: 150px;
border-right: 1px solid black;
display: flex;
justify-content: center;
position: relative;
}
.header .text {
width: 100%;
white-space: nowrap;
text-align: center;
overflow: hidden;
text-overflow: ellipsis;
}
.icons {
position: absolute;
right: 0;
}

How can I create a simple 3x3 grid inside an article that keeps aspect ratio?

I want to make a 3x3 grid of squares in CSS/HTML that doesn't pass the height of the page and is responsive.
I've tried changing the width and height of the article to make it smaller percentage wise but it makes it too small when on mobile and too big when on desktop.
.square-container {
display: flex;
flex-wrap: wrap;
}
.square {
position: relative;
flex-basis: calc(33.333% - 10px);
margin: 5px;
border: 1px solid;
box-sizing: border-box;
background: tomato;
font-size: 9vw;
}
.square::before {
content: '';
display: block;
padding-top: 100%;
}
.square .content {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.article1 {
border-style: solid;
border-width: 5px;
width: 100%;
height: 100%;
margin-left: auto;
margin-right: auto;
}
.h1 {
font-size: 3vw;
text-align: center;
}
<article class="article1">
<div>
<h1 class="h1">Text 1</h1>
</div>
<div class="square-container">
<div class="square">
<div class="content">0</div>
</div>
<div class="square">
<div class="content">1</div>
</div>
<div class="square">
<div class="content">2</div>
</div>
<div class="square">
<div class="content">3</div>
</div>
<div class="square">
<div class="content">4</div>
</div>
<div class="square">
<div class="content">5</div>
</div>
<div class="square">
<div class="content">6</div>
</div>
<div class="square">
<div class="content">7</div>
</div>
<div class="square">
<div class="content">8</div>
</div>
</div>
<div>
<h1 class="h1">Text 2</h1>
</div>
</article>
I want it to resize so that it's width and height are responsive and the height never exceeds the display (never have to scroll).

How to get 3 divs to align horizontally, with height of 100%, inside a container

EDIT: Alignment fixed by adding floats. Height still doesn't fill 100% though. Updated look: https://gyazo.com/4030d76c62c106fae5fbbb07f062efdd
I have a footer container in which I want to have 3 columns (I have made them green, white and red for now so it's easier for you to see). Currently they're stacking vertically but I want them to be beside eachother and have a height of 100% to fill the height of whatever the container's height is. Here is an image of what it looks liek at the moment, please ignore the large black boxes, these are just so I can see where stuff is on the page but will evenutally be transparent etc. https://gyazo.com/12d0642e5fd9518a663606668ec06311
They each have a width of 33% because I want to follow responsive practices and I've currently tried removing all padding and margins etc from every div.
Any help would be greatly appreciated, thank you.
HTML:
<div id="Page">
<div id="content" class="wrapper">
</div>
<div id="footer">
<div id="footerContainer">
<div id="footerLeft">
<p>
Test
</p>
</div>
<div id="footerCenter">
<p>
Test
</p>
</div>
<div id="footerRight">
<p>
Test
</p>
</div>
</div> <!-- footerContainer -->
</div> <!-- Footer -->
</div> <!-- Page -->
CSS:
#content {
background-color: black;
}
.wrapper {
width: 60%;
height: 100%;
margin: 0 auto;
}
#footer {
position: absolute;
width: 100%;
height: 300px;
background-color: black;
}
#footerContainer {
width: 60%;
max-height: 100%;
margin: 0 auto;
}
#footerLeft {
width: 33%;
height: 100%;
float: left;
background-color: darkolivegreen;
padding: 0;
}
#footerCenter {
width: 33%;
height: 100%;
float: left;
background-color: white;
padding: 0;
}
#footerRight {
width: 33%;
height: 100%;
float: left;
background-color: firebrick;
padding: 0;
}
Add display: flex to the #footerContainer rule, and change max-height: 100%; to height: 100%; in #footerContainer
#content {
background-color: black;
}
.wrapper {
width: 60%;
height: 100%;
margin: 0 auto;
}
#footer {
position: absolute;
width: 100%;
height: 300px;
background-color: black;
}
#footerContainer {
display: flex;
width: 60%;
height: 100%;
margin: 0 auto;
}
#footerLeft {
width: 33%;
background-color: darkolivegreen;
}
#footerCenter {
width: 33%;
background-color: white;
}
#footerRight {
width: 33%;
background-color: firebrick;
}
<div id="Page">
<div id="content" class="wrapper">
</div>
<div id="footer">
<div id="footerContainer">
<div id="footerLeft">
<p>
Test
</p>
</div>
<div id="footerCenter">
<p>
Test
</p>
</div>
<div id="footerRight">
<p>
Test
</p>
</div>
</div> <!-- footerContainer -->
</div> <!-- Footer -->
</div> <!-- Page -->
Here is a version where I simplified both markup and CSS
#content {
background-color: black;
}
.wrapper {
width: 60%;
height: 100%;
margin: 0 auto;
}
#footer {
position: absolute;
width: 100%;
height: 300px;
background-color: black;
display: flex;
justify-content: center;
}
#footer > div {
width: 20%;
}
#footerLeft {
background-color: darkolivegreen;
}
#footerCenter {
background-color: white;
}
#footerRight {
background-color: firebrick;
}
<div id="Page">
<div id="content" class="wrapper">
</div>
<div id="footer">
<div id="footerLeft">
<p>
Test
</p>
</div>
<div id="footerCenter">
<p>
Test
</p>
</div>
<div id="footerRight">
<p>
Test
</p>
</div>
</div>
<!-- Footer -->
</div>
<!-- Page -->
One for older browsers, using display: table
#content {
background-color: black;
}
.wrapper {
width: 60%;
height: 100%;
margin: 0 auto;
}
#footer {
position: absolute;
width: 100%;
height: 300px;
background-color: black;
}
#footerContainer {
display: table;
width: 60%;
height: 100%;
margin: 0 auto;
}
#footerContainer > div {
display: table-cell;
width: 33%;
}
#footerLeft {
background-color: darkolivegreen;
}
#footerCenter {
background-color: white;
}
#footerRight {
background-color: firebrick;
}
<div id="Page">
<div id="content" class="wrapper">
</div>
<div id="footer">
<div id="footerContainer">
<div id="footerLeft">
<p>
Test
</p>
</div>
<div id="footerCenter">
<p>
Test
</p>
</div>
<div id="footerRight">
<p>
Test
</p>
</div>
</div>
<!-- footerContainer -->
</div>
<!-- Footer -->
<!-- Footer -->
</div>
<!-- Page -->
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
#container {
width:100%;
height:100%;
}
#div1 {
width:33%;
display:inline-block;
float:left;
height:100%;
}
#div2 {
width:33%;
display:inline-block;
height:100%;
}
#div3 {
width:33%;
display:inline-block;
float:right;
height:100%;
}
</style>
</head>
<body>
<div id="container">
<div id="div1"><!--
--><div id="div2"><!--
--><div id="div3">
</div>
</body>
</html>
If the second div isn't perfectly aligned, try setting #container text-align to center. Is very important to use the comments to delete the space between the divs.
Add float: left to the 3 elements.
Don't repeat the properties, combine the selectors with comma.
To stretch the elements you will need to change max-height to height on #footerContainer.
#content {
background-color: black;
}
.wrapper {
width: 60%;
height: 100%;
margin: 0 auto;
}
#footer {
position: absolute;
width: 100%;
height: 300px;
background-color: black;
}
#footerContainer {
width: 60%;
height: 100%;
margin: 0 auto;
}
#footerLeft,
#footerCenter,
#footerRight {
float: left;
width: 33%;
height: 100%;
padding: 0;
}
#footerLeft {
background-color: darkolivegreen;
}
#footerCenter {
background-color: white;
}
#footerRight {
background-color: firebrick;
}
<div id="Page">
<div id="content" class="wrapper">
</div>
<div id="footer">
<div id="footerContainer">
<div id="footerLeft">
<p>
Test
</p>
</div>
<div id="footerCenter">
<p>
Test
</p>
</div>
<div id="footerRight">
<p>
Test
</p>
</div>
</div>
<!-- footerContainer -->
</div>
<!-- Footer -->
</div>
<!-- Page -->

Resize div to fit screen

When the text is added on top,the div moves down and the text on bottom is not visible. I want the divs to resize so that everything fits into container keeping the width and height to 100%.
Is there are any way to do this with CSS or do I need JavaScript?
body,html {
margin: 0;
padding: 0;
}
#container {
position: absolute;
width:100%;
height: 100%;
overflow: hidden;
}
.img {
background: blue;
width: 100%;
height: 50%;
display: inline-block;
vertical-align: top;
}
<div id="container">
<p>Text 1</p>
<div class="img"></div>
<div class="img"></div>
<p>Text 2</p>
</div>
You could use CSS flex for this.
It could look something like this:
body,html{
margin: 0;
padding: 0;
}
#container{
position: absolute;
width:100%;
height: 100%;
display:flex;
flex-direction: column;
}
.img{
background: blue;
width: 100%;
height: 50%;
vertical-align: top;
}
<div id = 'container'>
<p>Text 1</p>
<div class="img"></div>
<div class="img"></div>
<p>Text 2</p>
</div>
Fiddle
Using jquery you can achieve like below. Count total number of tags in container div and divide the 100% height among those element. SO all the items will be visible with overflow:hidden
Please check below snippet.
var itemLength = $('#container *').length;
$('#container *').css("height",(100/itemLength)+"%");
body,html{
margin: 0;
padding: 0;
}
#container{
position: absolute;
width:100%;
height: 100%;
overflow: hidden;
}
.img{
background: blue;
width: 100%;
//height: 50%;
display: inline-block;
vertical-align: top;
}
p,img,div{
padding:0;
margin:0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id = 'container'>
<p>Text 1</p>
<div class="img"></div>
<div class="img"></div>
<p>Text 2</p>
</div>
Change the height of .img to 40%. Because taking 50% height is making it consume the entire height.
body,html{
margin: 0;
padding: 0;
}
#container{
position: absolute;
width:100%;
height: 100%;
overflow: hidden;
background: #ccc;
}
.img{
background: blue;
width: 100%;
height: 40%;
display: inline-block;
vertical-align: top;
}
<div id = 'container'>
<p class="text1">Text 1</p>
<div class="img"></div>
<div class="img"></div>
<p class="text2">Text 2</p>
</div>
Css Code
body,html,p {
margin: 0;
padding: 0;
}
Script
$(function(){
var containerHeight= $('#container').height();
var pfirstHeight=$('#container p').eq(0).height();
var pbottomHeight=$('#container p').eq(1).height();
var imgHeight=(containerHeight-pfirstHeight-pbottomHeight)/2;
$('.img').height(imgHeight);
});

Categories