make elements block if parents are flex boxes - html

JSFIDDLE: https://jsfiddle.net/bnfsnm40/
Markup:
<div class="card">
<div class="card-header">Download stats</div>
<div class="card-block">
<div class="statistics">
<span class="day statistic">
<div class="count">100</div>
<div class="rank">10th</div>
<div class="icon text-success">
<i class="fa fa-line-chart "></i>
+4
</div>
</span>
What i want to do:
count, rank and iconshould be display: blockso they are under each other.
if i set them display: block they simply do not act like i expect a normal block element will act, they still sit next to each other rather then top to bottom.
.card-block {
.statistics {
display: flex;
justify-content: space-around;
.statistic {
height: 65px;
display: flex;
.count {
display: block;
width: 100%;
}
.rank {
display: block;
width: 100%;
}

There are 2 options for flex displaying items so they are "under" each other vertically.
Option 1 - Set flex-wrap:wrap; on the parent container and width:100%; on the children.
Option2 - Set flex-direction:column; on the parent container.

Related

Position icon in the middle of the text

I am having an issue with positioning in CSS. Now I have an icon and text like this :
Icon
But I want to make the icon go to the middle of the text. How do I do that?
You can use Flex.
Live code: Codepen
HTML:
<div class='alert'>
<span class='alert-icon'>icon</span>
<div class='alert-content'>
<div>text</div>
<div>text</div>
<div>text</div>
</div>
<span class='alert-close-icon'> close icon </span>
</div>
CSS:
.alert {
background-color: red;
color:#fff;
display: flex;
align-items: center;
justify-content: space-between;
width: 250px;
border-radius: 6px;
padding: 10px 10px
}
Just add the images and replace them with the text inside .alert-icon .alert-close-icon
Just use display: flex and align-items: center on the parent container of two block of elements to aligns.
.inlineElements {
display: flex;
}
.alignItemsCenter {
display: flex;
align-items: center; /* Pack items around the center */
}
.content {
margin: 0 10px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" rel="stylesheet"/>
<div class="inlineElements">
<div class='alignItemsCenter'>
<i class="fa-regular fa-circle-xmark"></i>
<div class="content">
<div>
Hello
</div>
<div>
Display
</div>
<div>
Flex
</div>
</div>
</div>
<i class="fa-solid fa-xmark"></i>
<div>

How to Set Flexbox child background to 100% height and center text vertically

I want to make the background color fill the area so it's always the same height for the longest amount of text, and center the text vertically, regardless of how many lines it is. I don't want to set a fixed height on the parent if possible as that may change.
.flexbox {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin-left: -8px;
margin-right: -8px;
}
.flexbox .sm-col-3 {
width: calc(1/3 * 100% - 16px);
}
.entry {
position: relative;
}
.entry-image {
display: block;
margin: 0 auto;
}
.entry-title {
margin: 0
}
.entry-title-link {
position: absolute;
bottom: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
padding: 8px 9px 9px;
background: rgba(0, 87, 149, 1);
color: #fff;
width: 100%;
}
<div class="articles-container flexbox">
<div class="entry sm-col-3">
<div class="entry-header">
<a href="#" class="entry-image-link"><img
src="https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-6_large.png"></a>
</div>
<div class="entry-content">
<h2 class="entry-title">
Some Long Wrapping Two Line Text
</h2>
</div>
<div class="entry-footer"></div>
</div>
<div class="entry sm-col-3">
<div class="entry-header">
<a href="#" class="entry-image-link"><img
src="https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-6_large.png"></a>
</div>
<div class="entry-content">
<h2 class="entry-title">
One Line Text
</h2>
</div>
<div class="entry-footer"></div>
</div>
</div>
You should think of this problem in terms of 2 different layouts.
the first one is to put your entry divs next to each other, 3 per line, same height each. That's the flex row you are using on .flexbox
the second one is within each entry div, to put the image on top and the link on the bottom. That's what I'm proposing here with another flex layout, nested inside the first one.
So the way to do this is to apply flex and column on .sm-col-3 to create the nested flex layout. And then it's just up to you how you need to allocate the space. The most common way to do it in this type of case would be to allocate a fixed size (or at least fixed ratio) to the image on top, and then put a flex: 1 on the text at the bottom so that it will occupy everything that's left, thus occupying the same amount of space on each entry.
Now if you also need to vertically center the next in that bottom section .entry-content, that is a 3rd problem to be solved.
the box at the bottom should have its content vertically centered
Except that now that we've divided the problem into its sub-problems, that 3rd one is easy to solve (tons of tutorials online on how to vertically center something within its parent). But since we're doing flexboxes here, let's use that a third time. That's going to be display: flex and align-items on .entry-content.
.flexbox {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin-left: -8px;
margin-right: -8px;
}
.flexbox .sm-col-3 {
width: calc(1/3 * 100% - 16px);
display: flex;
flex-direction: column;
}
.entry {
position: relative;
}
.entry-image {
display: block;
margin: 0 auto;
}
.entry-content {
flex: 1;
background: rgba(0, 87, 149, 1);
padding: 8px 9px 9px;
display: flex;
align-items: center;
}
.entry-title {
margin: 0;
}
.entry-title-link {
text-align: center;
color: #fff;
width: 100%;
}
<div class="articles-container flexbox">
<div class="entry sm-col-3">
<div class="entry-header">
<a href="#" class="entry-image-link"><img
src="https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-6_large.png"></a>
</div>
<div class="entry-content">
<h2 class="entry-title">
Some Long Wrapping Two Line Text
</h2>
</div>
<div class="entry-footer"></div>
</div>
<div class="entry sm-col-3">
<div class="entry-header">
<a href="#" class="entry-image-link"><img
src="https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-product-6_large.png"></a>
</div>
<div class="entry-content">
<h2 class="entry-title">
One Line Text
</h2>
</div>
<div class="entry-footer"></div>
</div>
</div>

Flexbox - Don't move centered columns if width changes

I have a frustrating problem with the otherwise great flexbox capabilities. I have the following layout with a centered column
The problem is, if one of the texts in the row grows or shrinks, then the FB/IG icons will not be in the same column line anymore. See what happens:
How can I achieve for variable width texts to not make the element grow to the left, but make the FB and IG icons actually stay in the same line no matter the variable texts??
Here is the code
.test-links {
display: flex;
flex-direction: column;
}
.test-link {
display: flex;
justify-content: center;
align-items: center;
}
<div class="test-wrapper">
<img class="test-img" src="path" />
<div class="test-links">
<a class="test-link">
<i class="fb"></i>
<span>Test</span>
</a>
<a class="test-link">
<i class="ig"></i>
<span>LongerText</span>
</a>
</div>
</div>
Thank you for your help!
.test-links {
display: flex;
flex-direction: column;
}
.test-link {
display: flex;
justify-content: left;
align-items: center;
width:100px;
margin:0 auto;
}
.test-wrapper
{
text-align:center;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<div class="test-wrapper">
<img class="test-img" src="https://dummyimage.com/100x100/000/fff" />
<div class="test-links">
<a class="test-link">
<i class="fb fa fa-facebook"></i>
<span>Test</span>
</a>
<a class="test-link">
<i class="ig fa fa-instagram"></i>
<span>LongerText</span>
</a>
</div>
</div>
I used <img src="http://via.placeholder.com/20x20" /> instead of icons, so to render something. position: absolute for text does the job.
Following MDN's definition:
[position] absolute: the element is removed from the normal document flow, and no space is created for the element in the page layout. It is positioned relative to its closest positioned ancestor, if any; otherwise, it is placed relative to the initial containing block. Its final position is determined by the values of top, right, bottom, and left.
... so left:100% moves it to the left for whole width of parent's element, which is only an icon. You can create a distance between icon/image and text using margin-left for text. position: relative for link makes it a hook for position of absolute child.
You can adjust precise values.
Snippet
.test-wrapper {
display: flex;
flex-direction: column;
align-items: center;
}
.test-links {
display: flex;
flex-direction: column;
align-items: center;
margin: 10px 0 0 0;
}
.test-link {
position: relative;
}
.test-link span {
position: absolute;
top: 0;
left: 100%;
}
<div class="test-wrapper">
<img class="test-img" src="http://via.placeholder.com/50x50" />
<div class="test-links">
<a class="test-link">
<img src="http://via.placeholder.com/20x20" />
<span>Test</span>
</a>
<a class="test-link">
<img src="http://via.placeholder.com/20x20" />
<span>LongerText</span>
</a>
</div>
</div>
Since, span cannot take width, use p instead and then add the following class to you code:
.test-link p{
width: 50px;
height:auto;
word-break:break-all;
text-align:left;
}
And then you will achieve the desired format.
Here is a link to the fiddle supporting this answer.
Here is the snippet:
.test-links {
display: flex;
flex-direction: column;
}
.test-link {
display: flex;
justify-content: center;
align-items: center;
}
.test-link p{
width:50px;
height:auto;
word-break:break-all;
text-align:left;
}
<div class="test-wrapper">
<div class="test-links">
<a class="test-link">
<img src="http://via.placeholder.com/20x20">
<p>Test</p>
</a>
<a class="test-link">
<img src="http://via.placeholder.com/20x20">
<p>LongerText</p>
</a>
</div>
</div>
Hope this was helpful.

Divs with same class adjust to different content

I have three divs in a row next to each other. They have the same class and same structure, but their content is different, particularly in length.
My problem is, that all three divs take the height of the one with the "longest" content instead of adjusting to their individual content.
Here's my HTML:
<main class="content">
<div class="column last-match">
<div class="image-wrapper">
<img src="default_thumbnail.jpg"/>
</div>
<div class="text-wrapper">
<a class="heading" href="#"><p class="heading">A Heading</p></a>
<p class="post-excerpt">Some text</p>
Read More
</div>
</div>
<div class="column last-match">
<div class="image-wrapper">
<img src="default_thumbnail.jpg"/>
</div>
<div class="text-wrapper">
<a class="heading" href="#"><p class="heading">A Heading</p></a>
<p class="post-excerpt">Some text that's longer</p>
Read More
</div>
</div>
<div class="column next-matches">
<div class="image-wrapper">
<img src="next_matches.jpg"/>
</div>
<div class="text-wrapper">
<p class="heading">List Heading</p>
<ul class="match-list">
<li class="match">some list item</li>
<li class="match">some list item</li>
</ul>
</div>
</div>
</main>
And the basic CSS:
.content {
display: flex;
flex-wrap: nowrap;
}
.column {
display: flex;
flex-direction: column;
margin: 60px 20px;
min-height: 100px;
width: 33%;
}
.image-wrapper {
width: 100%;
height: 260px;
overflow: hidden;
}
.image-wrapper img {
width: 100%;
height: auto;
}
.post-excerpt {
margin-bottom: 20px;
}
.button {
display: block;
float: left;
margin-bottom: 20px;
padding: 10px;
}
.match {
font-size: 1em;
padding-top: 15px;
}
Here's my code on JSFiddle: https://jsfiddle.net/4h0g73sp/5/
As you will see, the columns will take the height of the one with the most text in it. What I want is them to adjust to their content, so that they have different heights if necessary.
I don't know if it's noteworthy, that I'm working with Wordpress, so these columns are originally inside of some php. If that's important I'm happy to share the code with you, so let me know :)
The issue is because align-items on the flex container defaults to stretch so the flex items takes the height (rows) of the tallest item.
Simply set it to flex-start
.content {
display: flex;
align-items: flex-start;
}
https://jsfiddle.net/4h0g73sp/9/
I have also removed flex-wrap from .content because the default is no wrap so there is no need to declare it
Check https://css-tricks.com/snippets/css/a-guide-to-flexbox/ it's very useful and demonstrates flex fairly well

Block grid/inline-flex issue because of text length

I've got a block grid of squares with text inside each. Everything works fine when there is only one line of text. More text in a square makes it move below the others and break the grid.
The other problem is that I would like one square to have an additional line of text at the top as shown by the class="notice". But I can't get this to work either.
I've created a jsfiddle to show more clearly what the issue is. I've had a look through this guide on flexbox but can't seem to solve the issue, not sure if it is related. Any help is greatly appreciated for a newbie.
<body>
<div class="container">
<div class="products">
<div class="product">
<p>Apples</p>
<span class="link"></span>
</div>
<div class="product">
<p class="notice">You won't find cheaper</p>
<p>Best price you will find on grapes</p>
<span class="link"></span>
</div>
<div class="product">
<p>Orange</p>
<span class="link"></span>
</div>
<div class="product" id="no">
<p>Best price you will find on grapes, bananas, kiwis</p>
<span class="link"></span>
</div>
<div class="product">
<p>Orange</p>
<span class="link"></span>
</div>
<div class="product">
<p>Orange</p>
<span class="link"></span>
</div>
</div>
</div>
</body>
.products {
text-align:center;
}
.product {
background-color: red;
display: inline-flex;
height: 10em;
margin-bottom: 10px;
position: relative;
width: 10em;
justify-content:center;
align-items:center;
}
.product p {
color: black;
}
.product p.notice {
font-size: 14px;
color: yellow;
}
.link {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 1;
}
.product:hover, div.product:focus {
background-color: green;
}
Not sure why you need display: inline-flex for each of your product items. You could simply make the parent a flex container with display: flex, making all product items flex items.
HTML (no changes)
CSS (adjusted sections only)
.products {
display: flex; /* establish primary flex container */
flex-wrap: wrap; /* enable flex items to wrap */
justify-content: center; /* center flex items horizontally, in this case */
}
.product {
height: 10em;
width: 10em;
margin: 5px;
position: relative;
display: flex; /* establish nested flex container */
flex-direction: column; /* stack flex items vertically */
justify-content: center; /* center flex items vertically, in this case */
align-items: center; /* center flex items horizontally, in this case */
background-color: red;
}
Revised Fiddle
inline-flex, inline-block,inline-table,inline, img, .. all of them stands on a baseline, you may use vertical-align:
.product {
background-color: red;
display: inline-flex;
vertical-align:top; /* HERE */
height: 10em;
margin-bottom: 10px;
position: relative;
width: 10em;
justify-content:center;
align-items:center;
}
https://jsfiddle.net/382m8wzg/11/