Keeping flexbox container centered when child text wraps [duplicate] - html

This question already has answers here:
Make container shrink-to-fit child elements as they wrap
(4 answers)
Closed 5 years ago.
I am trying to center two div elements side by side in a row with flexbox (display:flex).
The first div element, on the left, just has an image.
The second div element, on the right, has left-aligned inline text of unspecified length.
When the line of text is short enough to fit on one line, both divs are aligned and justified to the center as I expect.
When the line of text is long enough to wrap onto two lines, the second div element does not wrap itself around the content as I expect. Instead, it leaves a large white space on the right side of the div.
I mocked up an example here: http://codepen.io/anon/pen/NGqYQX?editors=110. Vary your browser window's width to see what I mean.
How can I set the second div element to shrink itself to fit the text, so that both div elements appear centered?
.flexbox-container {
display: flex;
justify-content: center;
align-items: center;
}
.div1 {
margin-right: 30px;
}
.div2 {
font-size: 48px;
line-height: 48px;
text-align: left;
}
<div class="flexbox-container">
<div class="div1">
<img src="http://dreamatico.com/data_images/kitten/kitten-2.jpg" width="150px">
</div>
<div class="div2">
This is an example of a line of text.
</div>
</div>
<br>
<div class="flexbox-container">
<div class="div1">
<img src="http://dreamatico.com/data_images/kitten/kitten-2.jpg" width="150px">
</div>
<div class="div2">
This is an example of a much loooooooooooooonger line of text.
</div>
</div>
Here is a Photoshop mockup showing what I am trying to do:

In order to achieve your goal (as specified in your second image) we need to make a few adjustments to your HTML and CSS. Everything can be done with flexbox.
HTML
<div id="flex-container-main">
<div class="flex-container-child">
<figure>
<img src="http://dreamatico.com/data_images/kitten/kitten-2.jpg" width="150px">
</figure>
<p>This is an example of a line of text.</p>
</div>
<div class="flex-container-child">
<figure>
<img src="http://dreamatico.com/data_images/kitten/kitten-2.jpg" width="150px">
</figure>
<p>This is an example of a much loooooooooooooonger line of text.</p>
</div>
</div><!-- end #flex-container-main -->
CSS
#flex-container-main {
display: flex;
flex-direction: column;
align-items: center;
}
.flex-container-child {
display: flex;
align-items: center;
min-height: 127px;
width: 75%;
margin: 10px;
}
figure {
margin: 0 20px 0 0;
}
img {
width: 150px;
height: 127px;
vertical-align: bottom;
}
p {
font-size: 48px;
margin: 0;
}
Revised Codepen Demo
Here's what's happening...
Your question asks:
Keeping flexbox centered when text wraps to 2 or more lines
I am trying to center two div elements side by side in a row with flexbox (display:flex).
Let's quickly go over your two images.
Image 1
Image 2
In image 1 all flex items are actually centered. The blue highlight from Chrome Dev Tools emphasizes this point. Each item is perfectly centered on the screen.
Yes, it does get a bit clunky as you re-size the screen smaller – mostly because of the large font size – but the flex items remain centered nonetheless.
In image 2, the flex items are not evenly centered. What you've created in your mock-up is more like a column containing both flexboxes, and the column is centered. But individually only the first row is centered on the screen.
A couple of notes about your code:
With justify-content declared on the flex containers, you are centering the flex items. The flex container itself is not centered.
Since both flexboxes are direct children of the <body>, and <body> has no defined width, the flexboxes align themselves in relation to the viewport.
So to achieve the effect you want we can wrap all your existing mark-up in a new flex container (#flex-container-main). This converts the original flex containers into flex items, which can then be evenly centered as a group.
The new flex items (now classed as .flex-container-child) are given a width to create space and a minimum height based on the height of the image. Each flex item is also declared a flex parent (display: flex) which allows us to use flex properties on child elements. In particular, this is useful for vertically centering the text (as shown in your images).
(Note that my use of HTML semantic elements is not necessary for the code to work. If you prefer the original div tags just swap them back. The important adjustment is the new parent container.)
Lastly (and this may not be important to your layout but just in case), browsers normally give images a small gap of whitespace under their bottom border. This is used to accommodate descenders. With vertical-align: bottom, this space is removed. (For more details see my answer about descenders.)

Related

Can I vertically align inline blocks based on their children?

To illustrate this:
div {
border: 1px solid #000;
}
.ib {
display: inline-block;
}
.vm {
vertical-align: middle;
}
<div class="container">
<div class="col ib vm">
<div>aaa<br>a</div>
<div>b<br><br>b</div>
</div>
<div class="col ib vm">
<div>a<br><br><br><br>a</div>
<div>b<br><br>bbbbbbbbbb</div>
</div>
</div>
Here we have two inline blocks (i.e. .col), and they're vertically aligned at the middle. The question is:
Can I make the .cols vertically aligned by the middle of the inner children? (For example, the children containing "b".)
Or do I have to use JavaScript to calculate the position and apply transform?
As each .col may contain multiple children and I have many such .cols, implementation without JavaScript would be great.
Any solutions with grid, or flex, layout are OK.
The desired result is like the following image:
The .cols should be vertically moved such that the middle of their second children (regardless of the middle of the two .cols) are aligned.
I don't think this is possible with only CSS. If you need exactly this behavior the best thing you can do is probably to calculate needed margin-top for appropriate column using JavaScript. With correct margin second rows will appear as vertically centered.
If overlapping behavior can be sacrificed, you can place content in rows instead of columns and vertically center contents of second row.

Text Align Property is not working for Span Tag

There is section inside which i have defined text-align as left for a line but its not taking effect for some reason
<section id="topic1">
This is a centered Heading for Topic 1<br>
<span class="text">This is a left aligned line</span>
</section>
section {
text-align: center;
height: auto;
width: 100%;
}
.text {
display: inline-block;
text-align: left;
}
I tried display: block for text span tag in above code and text got aligned to left but i am looking for a alternative way to do this
Reason for finding alternative way - Even tho block display is aligning text to left , keeping display as block for all the span tags within my webpage increases the space between each span tag for some reason
Practical example below
<span class="text">This is line 1</span><br>
<span class="text">This is line 2</span>
.text {
display: block;
}
If you check output of above code there would be space between line 1 and 2 because of display block .
I am okay with using display : block to make text align work for span tag
But then this unnecessary space created by block display bothers me
Isn't there any way to avoid that unnecessary space ( seen between line 1 and 2 ) created while using block display
An inline-blockelement is only as wide as its contents, in your case NOT the full width of the container.
In their container inline-blocks are aligned according to the text-align setting of the parent element (= the container, in your case #topic1), thats why they are called INLINE-blocks.
So if you want it left-aligned, you have to change the alignment of section to left. And wrap your to be centered text in a heading element (like <h1>...</h1>, wich is a block element having 100% width by default) to which you apply text-align: center. And BTW, that would also improve the semantical quality of the HTML - headers should be wrapped in header tags.
About "unneccessary vertical space between lines": That the default margin-top and margin-bottom of these elements - you can reduce those by defining them in the CSS for the according elements)
You can do something like this using margin. This will allow you to adjust the spacing between the blocks. Also, you can remove the br tags.
section {
text-align: center;
height: auto;
width: 100%;
}
.text {
display: block;
text-align: left;
margin: 10px 0;
/* CHANGE THIS VALUE */
}
<section id="topic1">
This is a centered Heading for Topic 1
<span class="text">This is line 1</span>
<span class="text">This is line 2</span>
</section>
You have a space after the period.
To select class="text", use:
.text
not
. text
Try adding float: left instead of text-align:left. As span element or inline-block element take only fit width. float will help align the item with respect to parent.
https://codepen.io/pratik-sangami/pen/dybKMVz

Equal Height Columns - Flexbox & flex-wrap: wrap

i'm working on a layout and I can't figure out how to get these columns to be equal height, specifically the green areas when the text wraps. Can you help?
My html template, with more .category-containers inside...
<div class="flex-container">
<div class="category-container">
<a href="#" class="img-gallery-col medium-internal-page-static-image" style="background-image: url('http://placehold.it/800/800');">
</a>
<h4 class="text-center">Salads & Sides</h4>
</div>
</div>
My css for the flex-container is...
.flex-container {
width: 100%;
display: flex;
flex-wrap: wrap;
align-items: flex-start;
}
Here's a coden link if that helps http://codepen.io/johnsonjpj/pen/evopaV?editors=1100
EDIT: I have updated the pen and added a height to the category-container and also made it display: flex. Then I added flex-grow to the h4. How can I get it vertically center inside that green area?
You have no heights defined anywhere in your code. Therefore, there is no reason for your text blocks to have equal height. Their height is defined by the content, which is a default setting (height: auto).
You need to define a height somewhere in your layout, whether high up on the body element or on a container element closer to the text. You can then establish equal heights and use flex properties for vertical and horizontal alignment.
As you resize the page, there's points which all of the text boxes are on one line, and points where they're all on two lines (resize browser to wide/narrow).
Since you have this issue in a middle ground of sorts, I would recommend using CSS #media queries to change the height property of .category-container h4 to predetermined values which you know will look okay.

When a flexbox item has wrapping text the item fills the container and has extra whitespace at the end

Using a flexbox layout, I have a container with three divs in it. What I'm going for is the first div hugging the left edge of the container while the remaining two divs snuggle up on the right edge of the container. I'm admittedly very new to using the flex layout, but it seems straightforward enough.
Simple html:
<div class="container">
<div class="one">Left</div>
<div class="two">Middle</div>
<div class="three">Right</div>
</div>
And associated css:
.container{
display: flex;
align-items: center;
}
.one{
margin-right:auto;
}
The above code usually displays exactly as intended, and for most cases is perfect. Where trouble rears up is when, for example, that third item has enough text to wrap. When this happens the third item fills with whitespace to the right of the text, leaving no space between items one and two. It is subtle with small words, but pretty obvious with two large words that break right in the middle. The following codepen explains it better than I can.
Codepen showing the issue: http://codepen.io/camwheel/pen/XjjyOx
Am I abusing/misusing flex syntax here, or is there a legitimate issue with wrapped text in a flex item? More importantly in the short term, is there anything I can do to get around this issue?
If your divs only contain text then you can do the following:
Skip flexing the last item
text-align: right on the middle element
.container {
display: flex;
background: salmon;
}
.one, .two {
flex: 1;
}
.two {
text-align: right;
}
<div class="container">
<div class="one">Left</div>
<div class="two">Middle</div>
<div class="three">Right</div>
</div>
As Michael_B pointed out in comments, this isn't a flex issue. It comes down to a limitation of CSS. Parent items don't know when child items shrink (which happens to the width when text wraps) and so can't collapse back down. For a more in depth assessment see his earlier post here.

Display:table + display: table-cell does vertical align but divs have nonsense widths

I have a code to create wrapper divs containing elements I want to be vertically centered.
Ok. This works fine for me, I can have a given height for top-parent container or a given height for one of the elements contained (img, span, etc). I have always a right vertically centered of elements (this is what I want)
But however I have this error.
The widths of divs have an arbitrary value, as if the browser distributed the space.
I cannot use 'float' because then the table-trick does not work.
The next example I have three divs and I have arbitrary widths....
I'd like the first and second divs aligned to the left, and the third to the right.
But I can't use float ,, this is the code ( the imgs are 'cut' , but you can see the pseudo-image)
<div style="display: table; width: 200px; background-color: #0099CC;">
<div style="vertical-align: middle; display: table-cell;">
<img src="data:image/png;base64,iVBORw0KGg..."=" width="32" height="82"></div>
<div style="vertical-align: middle; display: table-cell;">
<span>Load file</span></div>
<div style="display: table-cell; text-align: center; vertical-align: middle;">
<img src="data:image/png;base64,iVBORw0KGg..."=" width="32" height="32"></div>
</div>
Any idea would be really appreciated,
Use the following process:
Replace display:table with display:inline-block
Use a container div with position:relative
Use text-align: justify to spread out the elements equally
Use a nested div with position:absolute; right:0; to realign the third element
Here are some related questions:
How to stretch a fixed number of horizontal navigation items evenly and fully across a specified container
Styling overlapping annotations in text with HTML <SPAN> tags and CSS