CSS - Centered image and text below it - html

I want to display a centered image and, below it, a centered and bordered text that has a width equal to its container. I use:
<!DOCTYPE html>
<html>
<head>
<style>
.d1 {
text-align: center;
}
.d2 {
border: 1px solid red;
display: inline-block;
}
</style>
</head>
<body>
<div class="d1">
<img src="smiley.gif"><br>
<div class="d2">This is some text</div>
</div>
</body>
</html>
This works fine but, as I read, the use of <br> is an indication of poor semantic HTML and should be avoided. Is there a way to do this without the use of <br>?
Thanks

Flexbox to the rescue:
.d1 {
display: flex;
flex-flow: column;
justify-content: center;
}
.d2 {
border: 1px solid red;
}
img, .d2{
margin: 0 auto;
}
<div class="d1">
<img src="https://placekitten.com/200/300">
<div class="d2">This is some text</div>
</div>

The semantically correct element to use is the HTML5 figure element ( documentation here ) - this is a block level element and has the figcaption element and the image element contained within it.
The figcaption can be the first child (ie - before the image) or last child (after the image) and is also a block level element and can be centered with css.
<!DOCTYPE html>
<html>
<head>
<style>
figure {
text-align: center;
}
figcaption {
margin-bottom: 10px;
}
</style>
</head>
<body>
<figure>
<figcaption>This is a fluffy kitten</figcaption>
<img src="https://cdn.unifiedcommerce.com/content/product/small/30106.jpg" alt="fluffy kitten" width="100">
</figure>
</body>
</html>

Try using a div to enclose your image. A div is a block element, meaning, it will occupy 100% of the parent width. In your case, if the img tag is inside div, then all contents outside the div will be in the next line automatically.
img {
max-width: 100px;
}
.d1 {
text-align: center;
}
.d2 {
border: 1px solid red;
display: inline-block;
}
<div class="d1">
<div>
<img src="https://demo-res.cloudinary.com/image/upload/sample.jpg">
</div>
<div class="d2">This is some text</div>
</div>

You can try this.Just use margin for the text section instead of <br> tag. And then for positioning both of the image and text to center, use the following property:
display: flex;
justify-content: center;
align-items: center;
flex-flow: column;
<!DOCTYPE html>
<html>
<head>
<style>
.d1 {
display: flex;
justify-content: center;
align-items: center;
flex-flow: column;
}
.d2 {
border: 1px solid red;
margin-top: 5px;
}
</style>
</head>
<body>
<div class="d1">
<img src="https://www.w3schools.com/howto/img_snow.jpg">
<div class="d2">This is some text</div>
</div>
</body>
</html>

Related

Using flexbox, how to overlay an image and expand to fill parent container

In the following html I want the txt-box div to be centered in the container, overlay the image, and expand to fill the container. It should have a margin of equal width on all sides allowing part of the image to show like a thick border.
The html shown is passable for what I want except the vertical vs. horizontal margins are always slightly different as the browser window is resized.
I feel like what I have here is a hack and that I am using flex-grow incorrectly. I understand flex-grow works to allow the txt-box div to expand since it is the only element with a grow value. If I can get that resolved I should be able to simply set a margin on txt-box and it should work.
What am I not understanding about flex-grow?
.container {
display: flex;
align-items: center;
justify-content: center;
border: solid 2px red;
position: relative;
}
.container img {
width: 100%;
flex-grow: 0;
flex-shrink: 0;
}
.txt-box {
background-color: white;
display: flex;
padding: 5px;
border: solid 2px blue;
flex-grow: 1;
position: absolute;
width: 90%;
height: 80%;
}
<div class="container">
<img src="blocks.png" />
<div class="txt-box">
hello world
</div>
</div>
Thanks to Michael Benjamin for putting me on the path to enlightenment. I finally got it figured out. My original question was actually a portion of what I was trying to accomplish. The answers are to use background-image:url('...') and make sure the table and row elements are display:flex.
JSFiddle
<html>
<head>
<style>
.flex-table {
flex-flow:column;
}
.flex-row {
flex-flow:row;
}
.container {
align-items: center;
justify-content: center;
padding: 20px;
border: solid 2px red;
background-image:url('https://i.imgur.com/BF3ty6o.jpg');
background-size:cover;
background-repeat:no-repeat;
max-width:500px;
}
.txt-box {
justify-self:stretch;
align-self:stretch;
border: solid 2px blue;
background-color: rgba(192,192,192,0.5);
}
body, .flex-table, .flex-row, .container, .txt-box {
display:flex;
flex-grow:1;
}
#media (max-width: 768px) {
.flex-row {
flex-flow:column;
}
}
</style>
</head>
<body>
<div class="flex-table">
<div class="flex-row">
<div class="container">
<div class="txt-box">
hello world 1
</div>
</div>
<div class="container">
<div class="txt-box">
hello world 2
</div>
</div>
<div class="container">
<div class="txt-box">
hello world 3
</div>
</div>
</div>
<div class="flex-row">
<div class="container">
<div class="txt-box">
hello world 4
</div>
</div>
<div class="container">
<div class="txt-box">
hello world 5
</div>
</div>
<div class="container">
<div class="txt-box">
hello world 6
</div>
</div>
</div>
</div>
</body>
</html>
What am I not understanding about flex-grow?
Flex properties don't work on absolutely positioned children of a flex container.
§ 4.1. Absolutely-Positioned Flex
Children
As it is out-of-flow, an absolutely-positioned child of a flex
container does not participate in flex layout.
Therefore, flex-grow: 1 on txt-box is not doing anything. It's just being ignored.
Considering that you want the image simply laying in the background, while the text box has more requirements, I would suggest absolutely positioning the image and leaving the text box in the normal flow.
Then give the text box full width and height, with equal padding on the primary container to keep uniform "margins" across screen sizes.
Here's a demo, with a few extra features to help illustrate the concepts involved.
body {
height: 100vh;
display: flex;
margin: 0;
padding: 10px;
}
.container {
flex-grow: 1;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
position: relative;
border: solid 2px red;
}
img {
position: absolute;
height: 100%;
width: 100%;
object-fit: contain; /* also try 'cover' for demo */
}
.txt-box {
z-index: 1;
width: 100%;
height: 100%;
border: solid 2px blue;
background-color: rgba(192,192,192,0.5);
}
* {
box-sizing: border-box;
}
<div class="container">
<img src="http://i.imgur.com/60PVLis.png">
<div class="txt-box">hello world</div>
</div>
jsFiddle demo

Padding right when container wider than screen?

I have the following html tree:
div with padding: 2rem 1.25rem;
div with max-width: none so that it overflows past the screen's width
The padding is applied correctly on the top, bottom and left side, but not on the right.
I know what's the problem but I'm not sure how to solve it. The parent div has a width of 375px, which is the screen's width, whereas the child div has 890px. How can I make the parent expand like the child?
There are a few other ancestors for the parent div above. Do I need to make all of them expand?
<!DOCTYPE html>
<html>
<head>
<style>
.parent {
display: flex;
flex-flow: row nowrap;
padding: 2rem 1.25rem;
}
.child {
background-color: #f5f8ff;
border: 1px solid #eff5f5;
display: flex;
flex-flow: row nowrap;
min-width: 100vw;
}
.item {
align-items: center;
display: flex;
flex-flow: row nowrap;
justify-content: center;
height: 44px;
width: 256px;
}
</style>
</head>
<body>
<div class="parent">
<div class="child">
<div class="item">Foo</div>
<div class="item">Bar</div>
<div class="item">Baz</div>
<div class="item">Qux</div>
</div>
</div>
</body>
</html>
Your question is very vague but if you want your parent div to just basically always be just big enough to house your child div. You can try setting your parent div to display: inline.
.parentdiv{
display: inline;
}
And by not setting a width. The parent div will always just be big enough to hold its children divs.
Hope this helps.
Give this a try:
<!DOCTYPE html>
<html>
<head>
<style>
.parent {
display: flex;
flex-flow: row nowrap;
padding: 2rem 1.25rem;
}
.child {
background-color: #f5f8ff;
border: 1px solid #eff5f5;
display: flex;
flex-flow: row nowrap;
min-width: 100%;
}
.item {
text-align: center;
flex: 0 0 25%;
}
</style>
</head>
<body>
<div class="parent">
<div class="child">
<div class="item">Foo</div>
<div class="item">Bar</div>
<div class="item">Baz</div>
<div class="item">Qux</div>
</div>
</div>
</body>
</html>

How to make flexbox 'justify-content: space-between' have effect?

I want to create following layout, where a header (green) spans the full width of the screen and is made up of two elements:
a picture (pink), that is top-left aligned, and has the height of the next element
a text block (red), that is top-right aligned. It made of two stacked elements: a text div (yellow) and a button. The width button equals the text width.
The expected output is this:
My code is the following:
.header{
background-color: green;
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.flex-element{
display: inline-block;
}
.picture_container{
background-color: pink
}
.picture{
height: 100%;
}
.text_container{
background-color: red
}
.text{
background-color: yellow;
}
<div class="header">
<div class="flex-element picture_container">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/55/Tux_Enhanced.svg/154px-Tux_Enhanced.svg.png" alt="" class="picture">
</div>
<div class="flex-element text_container">
<div class="text">
AAAAAAAAAA <br>
BBB
</div>
<button type="button" name="button" style="width: 100%">foo</button>
</div>
</div>
and gives following output:
The problem is that there is no "space-between" the pink and the red block, and they are not top aligned. I know I could work around it using css grid, yet I'd like to know why it isn't working.
Question: How to make justify-content: space-between have any effect?
This might be a browser issue. Indeed, I am using Firefox Developer Edition 63.0b14 as a browser.
A hack was then to add display: -moz-box; in the .header css definition. It is strange, though, as "Prefixed property values (such as -moz-box) are no longer needed for flexbox to work in major browsers." (see Michael_B's comment). A less hacky solution would hence be still appreciated.
Full code:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>test</title>
<style media="screen">
.header{
background-color: green; 
display: -moz-box;
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.flex-element{
display: inline-block;
}
.picture_container{
background-color: pink
}
.picture{
height: 100%;
}
.text_container{
background-color: red
}
.text{
background-color: yellow;
}
</style>
</head>
<body>
<div class="header">
<div class="flex-element picture_container">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/55/Tux_Enhanced.svg/154px-Tux_Enhanced.svg.png" alt="" class="picture">
</div>
<div class="flex-element text_container">
<div class="text">
AAAAAAAAAA <br>
BBB
</div>
<button type="button" name="button" style="width: 100%">foo</button>
</div>
</div>
</body>
</html>
Please try below code
<style>
.header {
padding: 10px;
}
.picture {
width: auto;
}
.text_container {
margin: auto 0;
}
.picture_container {
display: block;
}
</style>

CSS - flexbox issue

Hello I am trying to have three groups of three buttons with each group appearing on a separate line, I managed to achieve this by just grouping them up with divs, however when i use flexbox to position the buttons in the center of the page, all the buttons appear on one line. Is there a way i could use flexbox for my positioning and still be able to have the buttons on separate lines?
html,body{
margin:0;
padding:0;
height:100%;
width:100%;
overflow: hidden;
}
.options{
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.options a{
color: inherit;
text-decoration: none;
}
<!DOCTYPE html>
<head>
<link rel="stylesheet" type="text/css" href="home.css">
<link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet">
</head>
<body>
<div class="options">
<div class="one">
<button>Maths</button>
<button>Computer Science</button>
<button>Physics</button>
</div>
<div class="two">
<button>Chemistry</button>
<button>Biology</button>
<button>Business Studies</button>
</div>
<div class="three">
<button>Philosophy</button>
<button>Geography</button>
<button>History</button>
</div>
</div>
</body>
</html>
.options{
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
exemple : https://www.w3schools.com/cssref/css3_pr_flex-flow.asp
Try adding this
flex-flow:column;

vertically centering two divs within body

This is a simplified version of a more complex problem. Suppose there are two divs within the body, which have to be vertically centered. Because of some other requirements DOM can't change. So only by changing css I need to vertically align them center. I have tried many other stackoverflow posts but so far couldn't make it work.
Here is my code:
<!DOCTYPE html>
<html>
<head>
<style>
body{
}
.div1{
display: block;
background: red;
width: 300px;
}
.div2{
display: block;
background: green;
width: 300px;
}
</style>
</head>
<body>
<div class="div1">
<p>This is div1</p>
</div>
<div class="div2">
<p>This is div2</p>
</div>
</body>
</html>
This is possible using flexbox.
html,
body {
height: 100%;
}
body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
See this CodePen