Vertically centered text in a dynamic height wrapper - html

I'd normally just use line-height for vertical centering, but on this occasion the layout I'm working to is a little trickier.
I've put together this jsfiddle to show where I'm at so far. All the CSS hacks suggest using table-cell trickery for this but I can only get it to work if the wrapper has an absolute height, so for me this text isn't vertically centered:
<div class="wrap">
<a href="#">
<img src="http://www.thekrausemouse.com/wp-content/uploads/2016/03/sample-1.jpg" />
<span class="text"><span>Text that might span multiple lines</span></span>
</a>
</div>
https://jsfiddle.net/fdtbvmcw/
What I basically need is for the text, regardless of how many lines it spans, to sit in the middle of the image. The image can't be a background-image and I can't attach fixed widths or heights to the wrapper.
The wrapper is simulating a responsive column within a bigger page template and I need the image to retain full width of that column you see. Other HTML can be added within the column if need be.
Thoughts?

Flexbox can do that...
.wrap {
height: auto;
position: relative;
width: 50%;
}
.wrap a img {
height: auto;
width: 100%;
}
.wrap a span.text {
height: 100%;
left: 0;
position: absolute;
text-align: center;
top: 0;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.wrap a span.text span {
color: #fff;
font-size: 20px;
font-weight: bold;
line-height: 1.25
}
<div class="wrap">
<a href="#">
<img src="http://www.thekrausemouse.com/wp-content/uploads/2016/03/sample-1.jpg" />
<span class="text"><span>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Id praesentium nihil iure amet dolore nulla totam modi </span></span>
</a>
</div>

I think is better use translateY, it works in more devices
//CSS
.wrap {
height: auto;
position: relative;
width: 50%;
}
.wrap a img {
height: auto;
width: 100%;
}
.wrap span {
color: #fff;
font-size: 26px;
font-weight: bold;
line-height: 30px;
vertical-align: middle;
top: 50%;
transform: translateY(-50%);
display:block;
position:absolute;
text-align:center;
}
//HTML
<div class="wrap">
<a href="#">
<img src="http://www.thekrausemouse.com/wp-content/uploads/2016/03/sample-1.jpg" />
<span>Text that might span multiple lines</span>
</a>
</div>
https://jsfiddle.net/MAXXALANDER/fdtbvmcw/2/

I would also use flex for your solution.
.wrap a .text {
height: 100%;
left: 0;
position: absolute;
text-align: center;
top:0;
display: flex;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
justify-content: center;
align-items: center;
}

Related

Css: How to add background color and overlay content on picture tag?

Basically I am trying to add a background color and some text over the image and center the content div.
As you can see on the screenshot, currently image takes only the 1/3 of the screen, but it should be full width.
What I am trying to achieve is below the screenshot.
I tried to make use of background-blend-mode: normal; or apply width:100% or aspect-ratio: 1/1 or flex:1 but image is still not full width.What I mean by that, is that image should be of the same width as the parent container.
Sandbox Link and code snippet below
body {
margin: 0;
padding: 0;
}
.container {
background-color: #13293d;
overflow: auto;
display: flex;
align-items: center;
position: relative;
column-gap: 15px;
width: 100%;
opacity: 1;
min-width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
}
.picture-container {
opacity: 0.1;
width: 100%;
flex: 1;
}
.content {
opacity: 1;
background-blend-mode: normal;
}
<div class="container">
<div class="picture-container">
<picture>
<source
media="(min-width:650px)"
srcset="https://i.stack.imgur.com/Pm2og.png"
/>
<img
src="https://i.stack.imgur.com/Pm2og.png"
alt="Flowers"
/>
</picture>
</div>
<div class="content">
<p class="text">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Sapiente
</p>
</div>
Any help will be appreciated
for image use to show in center display: flex,margin:0px auto
then the image will be showing in the center
if you want to show the image full screen then use widht:100%
set the img width to 100vw in css and remove "style="width: auto;" from html img element.
lang-css file
body {
margin: 0;
padding: 0;
}
.container {
position: relative;
background-color: #13293d;
overflow: auto;
display: flex;
align-items: center;
position: relative;
column-gap: 15px;
width: 100%;
opacity: 1;
min-width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
}
.picture-container {
opacity: 0.1;
width: 100%;
flex: 1;
}
.picture-container img {
width: 100vw;
}
.content {
opacity: 1;
background-blend-mode: normal;
}
.text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
lang-html file
<div class="container">
<div class="picture-container">
<picture>
<source media="(min-width:650px)" srcset="https://i.stack.imgur.com/Pm2og.png" />
<img src="https://i.stack.imgur.com/Pm2og.png" alt="Flowers" />
</picture>
</div>
<div class="content">
<p class="text">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Sapiente
</p>
</div>
</div>

How do you make a flex item break to the next line?

I have a basic html markup, where i am trying to use minimal html wrappers to achieve the design.
The button on the bottom should't align, it should always stay in the bottom.
So my goal is without adding more html wrappers, using flex, force a flex item(button) to drop to the next line. and the block title stay next to the image.
You can see what i mean checking it on mobile breakpoints.
Here are the screenshots with flex-wrap: wrap
And here is with flex-wrap: nowrap
As you see, in first example button is in the bottom as it should be, but block title is dropped to the next line, And in the second example (flex-wrap: wrap) block title is positioned correct, but the button is not in the bottom.
Here is the sandbox link and code example
body {
margin: 0;
padding: 0;
}
.container {
background-color: grey;
overflow: auto;
padding: 20px;
align-items: center;
display: flex;
position: relative;
column-gap: 15px;
flex-wrap: wrap;
/* //try nowrap */
width: 100%;
}
.logo-image {
align-self: flex-start;
}
.headline {
color: white;
}
.text {
color: white;
font-size: 16px;
margin-bottom: 20px;
}
.btn {
display: flex;
width: 100%;
}
button {
align-items: center;
background-color: black;
color: white;
flex: 0 0 100%;
justify-content: center;
margin: 0;
}
<div class="container">
<img src="download.png" width="50px" class="logo-image" alt="img" />
<span class="content">
<h4 class="headline">
Block Title
</h4>
<p class="text">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Sapiente
aliquid sit, cupiditate
</p>
</span>
<div class="btn">
<button>link</button>
</div>
</div>
Any help will be appreciated
You can make your span a block level element and set flex-grow to 1 but set flex-basis to something small, like 50% so it tries to be 50% of the width but will grow to fit the width. It then means when shrinking it will try to stay on the same line.
body {
margin: 0;
padding: 0;
}
.container {
background-color: grey;
overflow: auto;
padding: 20px;
align-items: center;
display: flex;
position: relative;
column-gap: 15px;
flex-wrap: wrap;
width: 100%;
}
/* added this --v */
.content {
display: block;
flex: 1 0 50%;
}
.logo-image {
align-self: flex-start;
}
.headline {
color: white;
}
.text {
color: white;
font-size: 16px;
margin-bottom: 20px;
}
.btn {
display: flex;
width: 100%;
}
button {
align-items: center;
background-color: black;
color: white;
flex: 0 0 90%;
justify-content: center;
margin: 0;
}
<div class="container">
<img src="https://www.fillmurray.com/200/200" width="50px" class="logo-image" alt="img" />
<span class="content">
<h4 class="headline">
Block Title
</h4>
<p class="text">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Sapiente
aliquid sit, cupiditate
</p>
</span>
<div class="btn">
<button>link</button>
</div>
</div>

align-items: center distorts height of parent

I want to build, something like a carousel, that you can slide using a scrollbar. In each of the slides, there's a single line of text that should be both horizontally and vertically centered.
Setting align-items: center changes height of the parent div.
.carousel {
width: 100%;
background-color: #dbdbdb;
overflow-y: visible;
overflow-x: auto;
white-space: nowrap;
}
.carousel .slide {
display: inline-flex;
width: 250px;
height: 150px;
margin: 10px 10px 10px 10px;
background-color: #FFF;
font-weight: bolder;
font-size: 15px;
white-space: pre-wrap;
align-items: center;
justify-content: center;
text-align: center;
text-align-last: center;
}
<div class="carousel">
<div class="slide">Lorem ipsum dolor</div>
<div class="slide">quisquam est qui dolorem ipsum quia dolor sit amet lorem ipsum</div>
<div class="slide">consectetur, adipisci</div>
</div>
Comment out the align-items and it fits alright. How should I resolve this issue?
The problem is not align-items: center. That's all good.
The problem is that your flex container is an inline-level box (display: inline-flex), which activates the vertical-align: baseline default setting.
Since your middle item has two lines of text, the box adjusts its baseline to line-up with its siblings. (Notice how all boxes line up when they each have a single line of text.)
Just override the default with vertical-align: bottom.
.carousel .slide {
vertical-align: bottom;
}
.carousel {
width: 100%;
background-color: #dbdbdb;
overflow-y: visible;
overflow-x: auto;
white-space: nowrap;
}
.carousel .slide {
display: inline-flex;
width: 250px;
height: 150px;
margin: 10px 10px 10px 10px;
background-color: #FFF;
font-weight: bolder;
font-size: 15px;
white-space: pre-wrap;
align-items: center;
justify-content: center;
text-align: center;
text-align-last: center;
vertical-align: bottom; /* NEW */
}
<div class="carousel">
<div class="slide">Lorem ipsum dolor</div>
<div class="slide">quisquam est qui dolorem ipsum quia dolor sit amet lorem ipsum</div>
<div class="slide">consectetur, adipisci</div>
</div>
Also note:
the problem doesn't exist when you remove align-items: center because the default value is stretch, which allows the text to align at the baseline (i.e., first line) across boxes regardless of the number of lines (demo)
flex-start would also work (demo)
flex-end would not (demo)
More details about vertical-align: baseline:
Why is there a vertical scroll bar if parent and child have the same height?

Bottom vertical align div in parent

Im having an issue with vertical aligning a button inside of its parent.
The button should be aligned to the bottom of the "info" div but I cannot get it to stick.
I cannot use "position: absolute" in this situation.
And i do not know the height of the main parent div beforehand.
HTML:
<div class="container">
<img src="http://placekitten.com/g/200/400" alt="" />
<div class="info">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloribus rem tenetur temporibus voluptas repellendus.</p>
<button>Button</button>
</div>
</div>
CSS:
* { box-sizing: border-box; }
.container {
width: 200px;
height: 700px; /* The height is variable!!! */
background: #ccc;
padding: 1em;
overflow: hidden;
}
a { display: block; height: 50%; }
a img { display: block; width: 100%; max-width: 100%; }
.info {
background: #fa0;
display: block;
height: calc(50% - 1em);
margin-top: 1em;
text-align: center;
}
.info p {
display: inline-block;
width: 100%;
vertical-align: top;
background: #a0f;
margin: 0;
}
.info button {
display: inline-block;
vertical-align: bottom;
}
As mentioned in some of the comments, position: absolute is the easiest way to do this. However, you said you're restricted on this factor, so here's an alternative using flexbox!
You need to see three properties on the parent element: display, flex-direction, and justify-content. Then put a margin on the child element to make sure its centered at the bottom. Here's an updated fiddle. No absolute position required : ) https://jsfiddle.net/jg8egtb1/
.info {
background: #fa0;
display: block;
height: calc(50% - 1em);
margin-top: 1em;
text-align: center;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.info button {
margin: 0 auto;
}

CSS to vertically align text to middle of div

What is the correct way to force text in a div to vertically align to the middle?
I have found a couple 'tricks', but I need something that works with a single line and multiple lines. Hopefully I am missing something stupid simple:
http://jsfiddle.net/rogerguess/DawFy/
.header {
display: inline-block;
text-align: center;
width: 123px;
background: green;
border-radius: 4px 4px 4px 4px;
height: 80px;
vertical-align: middle;
}
<div >
<div class="header">test1 </div>
<div class="header">some text that will wrap</div>
<div class="header">test3</div>
</div>
Change display: inline-block; to display: table-cell;
If your multi-line elements need to wrap for responsive reasons, then your best bet is with Flexbox. Due to the flakiness of Firefox's 2009 Flexbox implementation, it has to be handled slightly differently than you would do it for modern Flexbox implementations.
http://codepen.io/cimmanon/pen/mxuFa
<ul>
<li>One lorem ipsum dolor sit amet</li><!--
--><li>Two</li><!--
--><li>Three</li><!--
--><li>Four</li><!--
--><li>Five</li>
</ul>
li {
text-align: center;
vertical-align: middle;
/* fallback for non-Flexbox browsers */
display: inline-block;
/* Flexbox browsers */
display: -webkit-inline-box;
display: -moz-inline-box;
display: -ms-inline-flexbox;
display: -webkit-inline-flex;
display: inline-flex;
/* vertical centering for legacy, horizontal centering for modern */
-webkit-box-pack: center;
-moz-box-pack: center;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
/* modern Flexbox only */
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
/* legacy Flexbox only */
-webkit-box-orient: vertical;
-moz-box-orient: vertical;
}
I've made a quick example for you, using display: table-cell property on the parent div.
CSS:
.outer {
width: 500px;
height: 500px;
display: table-cell;
background-color: red;
vertical-align: middle;
}
.inner {
display: block;
width: 300px;
height: 200px;
margin: 0px auto;
background-color: yellow;
}
HTML:
<div class="outer">
<div class="inner">
</div>
</div>
http://jsfiddle.net/aKT42/
Try this, it will work.
<div class="greenBorder" id="outer">
<div id="middle">
<div class="greenBorder" id="inner">
Your Text Here
</div>
</div>
</div>
Css Class
#outer {
height: 100%;
overflow: hidden;
position: relative;
width: 100%;
display: table;
position: static;
}
div.greenBorder {
background-color: #39B9FF;
text-align: center;
color: white;
}
#middle[id] {
display: table-cell;
position: static;
vertical-align: middle;
width: 100%;
}
#middle {
position: absolute;
top: 50%;
}
http://jsfiddle.net/DawFy/16/
.header {
display: block;
text-align: center;
width: 123px;
background: green;
border-radius: 4px 4px 4px 4px;
height: 80px;
margin:0px auto;
}
li
{
list-style-type:none;
}
<div >
<li>
<div class="header">test1 </div>
<li>
<div class="header">some text that will wrap</div>
<li>
<div class="header">test3</div>
Try this dont know if its "correct" but works
Most of these solutions wouldn't work for me because either the height was manually specified (which I couldn't do) or things like inline-block and float would remove the ability for the an inner div to inherit the parent div's height. I ended up creating a table with two columns each containing my divs and then I had no issues vertically centering text.