Can I have a line between rows of flexbox? - html

I have a horizontal navigation, which is somewhat long, and needs to be rearranged for narrow displays. I used flexbox to make it reflow into multiple rows.
But with many rows, the division between the navigation items is not so obvious. I tried giving them a border on top, and it kinda works - but the border is, of course, only visible over the individual navigation options, not creating a nice dividing line between all flexbox rows.
Please view the snippet full page, there is a display problem when it's viewed within the post. Or use this fiddle. You may have to make your browser window narrow to see the navigation in multi row.
header {
height: 3em;
background-color: #fff;
}
#main {
height: 9em;
background-color: #5987d1;
}
footer {
height: 3em;
background-color: #a8a8a8;
border-top: 1px solid #0047b9;
}
ul.horizontal-nav {
background: rgba(72, 72, 72, 1);
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-ms-flex-direction: row;
flex-direction: row;
align-items: center;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-box-shadow: 0px 2px 1px 0px rgba(0,0,0,0.75);
-moz-box-shadow: 0px 2px 1px 0px rgba(0,0,0,0.75);
box-shadow: 0px 2px 1px 0px rgba(0,0,0,0.75);
list-style: none;
}
li.NavigationLi2, li.selected-branch-root {
padding: 0.75em 1em;
display: block;
border-top: 1px solid #2662c3;
}
li.selected-branch-root {
background: #2662c3;
}
li.NavigationLi2 > a, li.NavigationLi2 > a:visited {
color: #e6eeff;
text-decoration: none;
-ms-word-wrap: nowrap;
word-wrap: nowrap;
}
li.selected-branch-root > a, li.selected-branch-root > a {
color: #fff;
text-decoration: none;
-ms-word-wrap: nowrap;
word-wrap: nowrap;
}
<header>
</header>
<nav class="horizontal-nav">
<ul class="horizontal-nav">
<li class="selected-branch-root">Search
</li>
<li class="NavigationLi2">My models
</li>
<li class="NavigationLi2">Account
</li>
<li class="NavigationLi2">Management
</li>
<li class="NavigationLi2">Administration
</li>
<li class="NavigationLi2">Help
</li>
</ul>
</nav>
<section id="main">
</section>
<footer>
</footer>

Here is what I do lets say I have a flexbox container with 3 divs inside
<div class="flex">
<div>
<h2>Free Shipping</h2>
</div>
<div>
<h2>Everything In Stock</h2>
</div>
<div>
<h2>Largest Inventory</h2>
</div>
</div>
What I am playing with is in order to make a line right in the middle of the 3 div's / flex items simply just add another flex item between the divs like this:
<div class="flex">
<div>
<h2>Free Shipping</h2>
</div>
<img src="lib/xxx/img/ydivider.png" alt="divider"/>
<div>
<h2>Everything In Stock</h2>
</div>
<img src="lib/xxx/img/ydivider.png" alt="divider"/>
<div>
<h2>Largest Inventory</h2>
</div>
</div>
You can now see we have 5 flex items instead of 3. The 2 additional flex items I find are spaced correctly to be in the middle. Keep in mind if you go to to a breakpoint where you display as columns you will need a horizontal img at that point.

Assuming your philosophy allows you to: 1) Use flebox instead or ul for navigation; and 2) insert tags in your html specifically for aesthetic purposes, then I have a sugestion.
Create a wrapping div to your elements and add to it the CSS you'd like to span the row (background, border, padding...), and add to it the property flex: 1. You might also want to add to it min-width: fit-content (or max-content) to keep it from breaking lines.
I've added below the markup that would show it before and after the quick fix.
#flex-container {
display: flex;
flex-wrap: wrap;
}
#flex-container > div {
padding: 8px 24px;
border-bottom: 4px solid orange;
background: purple;
}
.flex-menu {
font-size: 13px;
font-family: sans;
color: white;
}
.fix {
flex: 1;
min-width: fit-content;
}
.force-break {
max-width: 340px;
}
<div class="force-break">
<h2>Plain</h2>
<div id='flex-container'>
<div class="flex-menu">Search</div>
<div class="flex-menu">My models</div>
<div class="flex-menu">Account</div>
<div class="flex-menu">Management</div>
<div class="flex-menu">Administration</div>
<div class="flex-menu">Help</div>
</div>
<h2>With fix</h2>
<div id='flex-container'>
<div class="fix"><div class="flex-menu">Search</div></div>
<div class="fix"><div class="flex-menu">My models</div></div>
<div class="fix"><div class="flex-menu">Account</div></div>
<div class="fix"><div class="flex-menu">Management</div></div>
<div class="fix"><div class="flex-menu">Administration</div></div>
<div class="fix"><div class="flex-menu">Help</div></div>
</div>
</div>

Related

How do I get flex elements not to grow on click?

Hobbyist who really sucks at css.
I have the following three divs:
The problem is, when I click on the middle one, the box grows, and so do the other two boxes:
How do I make boxes start off and stay the same size even after click. The reason the box is growing is do to adding the "arrow-icon"
Code looks like this:
HTML
<section class='modes-flex__options'>
<div class='options'>
<h2 class='options__title'>Options</h2>
<div class='options__item-container'id='1v1' onClick="selectedGameOption(this.id)">
<h3 class='options__item'>Player vs AI (1 v 1) </h3>
<div class='arrow-icon__div'>
<i></i>
</div>
</div>
<div class='options__item-container' id='1v1-tourny' onClick="selectedGameOption(this.id)">
<h3 class='options__item'>Player vs AI (Tournament)</h3>
<div class='arrow-icon__div'>
<i></i>
</div>
</div>
<div class='options__item-container' id='ai-v-ai-tourny' onClick="selectedGameOption(this.id)">
<h3 class='options__item' >AI vs AI (Tournament)</h3>
<div class='arrow-icon__div'>
<i></i>
</div>
</div>
</div>
</section>
CSS
.modes-flex{
display: flex;
margin-top: 3rem;
&__options{
flex:1;
display: flex;
justify-content: end;
}
&__description{
flex:1;
display: flex;
flex-direction: column;
}
}
.options{
margin-right: 5rem;
&__title{
font-size: 1.2rem;
padding-bottom:2rem;
}
&__item{
flex: 1;
padding-right: 5rem;
}
}
.description{
&__title{
font-size: 1.2rem;
padding-bottom:2rem;
}
}
.options__item-container {
padding: 1.5rem 1rem 1.5rem 1rem;
margin-bottom: 2rem;
box-shadow: 0 0 10px lightgrey;
border: 1px solid lightgrey;
display: flex;
align-items: center;
&:hover{
cursor: pointer;
}
}
.arrow-icon__div{
text-align: right;
}
.active-option{
background-color: $dark-navy;
color: white;
}
Tried to set min and max width and was still growing , just want them to stay even width after adding the icon.
You said it: The reason the box is growing is do to adding the "arrow-icon".
In my experience, in these situations, I always added to the default size of the boxes so that when another element (i.e. arrow-icon) is added, it doesn't change the size. (Because there is enough space in the box for arrow-icon to be added). With doing so, all the boxes remain the same through any actions.

How to fill remaining space on last line for wrapped text?

I'm trying to create a webapp where I need to render user entered title and content. I'd like to render all the action buttons related to the title on the same line as the last word of the title ("displays" in the demo) if the action bar fits, or on the next line if there's not enough space to fit whole action bar on the same line.
I've created a demo which results in correct rendering here: https://jsfiddle.net/mtrantalainen/h6qyv7a4/1/
(Note how this results in nice rendering in all cases, including the case where everything fits on one line on wide display, all to the way to case where buttons barely fit on a single line alone. I've tested the demo with Chrome and Firefox only.)
Same demo here inline:
header
{
display: flex;
flex-wrap: wrap;
gap: 0.5em;
}
header > span /* I would like to h1 here instead */
{
font-size: 2rem;
outline: dotted 1px #ddd;
}
.buttons
{
display: flex;
flex: 1 0 auto;
flex-wrap: nowrap;
}
.buttons a
{
display: flex;
align-items: center;
justify-content: center;
min-width: 44px;
min-height: 44px;
flex: 0 0 auto;
padding: 0.5rem;
box-sizing: border-box;
border: solid red 1px;
cursor: pointer;
}
.buttons .fill
{
flex: 1 0 auto;
background: yellow;
}
<header>
<span>Here's</span> <span>lots</span> <span>of</span> <span>text</span> <span>as</span> <span>a</span> <span>header</span> <span>which</span> <span>cannot</span> <span>easily</span> <span>fit</span> <span>on</span> <span>one</span> <span>line</span> <span>on</span> <span>most</span> <span>displays</span>
<div class="buttons">
<a>1</a>
<a>2</a>
<a>3</a>
<span class="fill"></span>
<a>4 with long label</a>
<a>5</a>
</div>
</header>
Screenshot (this is also the rendering I want):
The intent is to keep all the action buttons with red borders on the same line and fit the whole action button block on the line with the last word of the title, if possible. The yellow area in the middle of action bar would be transparent filler with zero or more pixels and allows positioning selected actions near the title or the right margin if there's extra space on line.
The demo works by wrapping every word in the title as a separate <span> element and flex-wrap is used to allow title to wrap and the action bar to follow on the same line.
However, this doesn't allow semantic markup because I cannot even wrap all the words in an <h1> element. In addition, the current demo doesn't play nicely with copy-pasting the title because every word will end up on separate line if copied.
Can anybody suggest any way to result in similar rendering using only HTML5 and CSS given following markup?
<header>
<h1>Here's lots of text as a header which cannot easily fit on one line on most displays</h1>
<nav class="actions">
<a>1</a>
<a>2</a>
<a>3</a>
<span class="fill"></span>
<a>4 with long label</a>
<a>5</a>
</nav>
</header>
Another possibility for the actions markup in semantic way would be
<div class="actionbar">
<nav class="titleactions">
<a>1</a>
<a>2</a>
<a>3</a>
</nav>
<nav class="extraactions">
<a>4 with long label</a>
<a>5</a>
</nav>
</div>
with the whole <header> as above. I used span.fill in the demo because it was easiest to implement and doesn't mess with the semantics too bad.
I am not sure that I understood your question well but is that what you are looking for?
header
{
display: flex;
gap: 0.5em;
}
header > h1/* I would like to h1 here instead */
{
font-size: 2rem;
outline: dotted 1px #ddd;
}
.buttons
{
display: flex;
flex: 1 0 auto;
flex-wrap: nowrap;
width: 40%;
}
.spanDiv { width: 60%}
.buttons a
{
display: flex;
align-items: center;
justify-content: center;
min-width: 44px;
min-height: 44px;
flex: 0 0 auto;
padding: 0.5rem;
box-sizing: border-box;
border: solid red 1px;
cursor: pointer;
}
.buttons .fill
{
flex: 1 0 auto;
background: yellow;
}
<header>
<div class="spanDiv">
<h1>Here's lots of text as eader which cannot easily fit on one lineon most displays</h1>
</div>
<div class="buttons">
<a>1</a>
<a>2</a>
<a>3</a>
<span class="fill"></span>
<a>4 with long label</a>
<a>5</a>
</div>
</header>
The least bad implementation I can figure out:
header
{
display: flex;
flex-wrap: wrap;
gap: 0.5em;
}
header > h1
{
display: contents;
}
header > span
{
font-size: 2rem;
outline: dotted 1px #ddd;
}
.buttons
{
display: flex;
flex: 1 0 auto;
flex-wrap: nowrap;
}
.buttons a
{
display: flex;
align-items: center;
justify-content: center;
min-width: 44px;
min-height: 44px;
flex: 0 0 auto;
padding: 0.5rem;
box-sizing: border-box;
border: solid red 1px;
cursor: pointer;
}
.buttons .fill
{
flex: 1 0 auto;
background: yellow;
}
<header>
<h1><span>Here's</span> <span>lots</span> <span>of</span> <span>text</span> <span>as</span> <span>a</span> <span>header</span> <span>which</span> <span>cannot</span> <span>easily</span> <span>fit</span> <span>on</span> <span>one</span> <span>line</span> <span>on</span> <span>most</span> <span>displays</span></h1>
<div class="buttons">
<a>1</a>
<a>2</a>
<a>3</a>
<span class="fill"></span>
<a>4 with long label</a>
<a>5</a>
</div>
</header>
Problematic parts remaining:
Copy-paste is still broken (tested with Chrome only).
The display: contents browser support is still a bit poor.
Every word in the title still needs a separate wrapper <span> element.
Words in the title cannot ever hyphenate.
span.fill needed to introduce the space.

Scroll container pushing parallel div to the right instead of creating a horizontal scroll

I am trying to make my scroll__container scroll on the x axis. However, whenever I add a new div to the container, it pushes the div I have on the right, further to the right and doesn't create a scrollbar.
Here is my code:
<div className="themesContainer">
<div className="themes__skinContainer">
<div className="themes__tag">
<h6>Skins</h6>
</div>
<div className="skins__container">
<h6>Primary Colors</h6>
<div className="scroll__container">
<div onClick={setBlackTheme} className="skin__option">
<p>Black</p>
</div>
<div onClick={setBlueTheme} className="skin__option">
<p>Blue</p>
</div>
<div onClick={setRedTheme} className="skin__option">
<p>Red</p>
</div>
<div onClick={setYellowTheme} className="skin__option">
<p>Yellow</p>
</div>
<div onClick={setGreenTheme} className="skin__option">
<p>Green</p>
</div>
<div onClick={setPurpleTheme} className="skin__option">
<p>Purple</p>
</div>
<div onClick={setOrangeTheme} className="skin__option">
<p>Orange</p>
</div>
<div onClick={setPinkTheme} className="skin__option">
<p>Pink</p>
</div>
</div>
</div>
</div>
And here is my css:
.themesContainer {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin: 0px 150px;
margin-top: 100px;
border-radius: 22px;
border-radius: 10px;
}
.themes__skinContainer {
max-width: 100%;
background-color: black;
overflow: none;
}
.themes__tag {
display: flex;
justify-content: flex-start;
}
.themes__tag > h6 {
font-family: Poppins;
font-size: 20px;
font-weight: 500;
background-color: black;
padding: 20px 25px;
margin: 0px;
color: white;
border-radius: 10px 0px 10px 0px;
}
.scroll__container {
display: flex;
overflow-x: auto;
}
.skin__option {
padding: 20px;
background-color: blue;
}
Using your code, I see a scrollbar:
Live Demo
However, on mobile devices the scrollbar is only visible while scrolling. This is normal behaviour. The same goes for viewing a page while Chrome devtools option Toggle device toolbar is enabled:
If you want to make scrollbars permanently visible on mobile, you will need to use vendor prefixes or implement a custom toolbar component. I recommend against doing so, because as I mentioned this is normal behaviour so there may not be any UX issues here.

Trying to make div height based on max content with flexbox and css font-size is ruining flex: auto

I have a flex container with multiple flex items, 2 of which I need to flex grow based on the text so all divs space out the same way.
I was able to accomplish this like this:
<div class="outer product-grid">
<div class="inner product-component">
<a class="image"><img class="product-image" /></a>
<a class="upper-text title">
Short Upper Text
</a>
<div class="lower-text author">
Short Lower Text
</div>
<h5 class="price"> <span>price</span> </h5>
</div>
<div class="inner">
<a class="image"><img class="product-image" /></a>
<a class="upper-text">
Long Upper Text - Long Upper Text
</a>
<div class="lower-text">
Long Lower Text - Long Lower Text
</div>
<h5 class="price"> price </h5>
</div>
<div class="inner">
<a class="image"><img class="product-image" /></a>
<a class="upper-text">
Even Longer Upper Text - Even Longer Upper Text
</a>
<div class="lower-text">
Even Longer Lower Text - Even Longer Lower Text
</div>
<h5 class="price"> price </h5>
</div>
</div>
SCSS
.outer {
display: flex;
flex: wrap;
.inner {
border: 5px solid yellow;
display: flex;
text-align: center;
margin-right: 1em;
margin-bottom: 1.5em;
width: 200px;
flex-direction: column;
font-size: 1.00em;
a.image{
border: 5px solid orange;
img {
width: em(160px);
height: em(210px);
}
}
a.upper-text {
border: 5px solid red;
flex: auto;
margin: 0.2em auto;
line-height: normal;
}
.lower-text {
border: 5px solid green;
flex: auto;
}
}
}
My upper-text and lower-text need to be different sizes. When I put a font-size into either of those classes, I lose the whole flex grow.
You can try on my codepen https://codepen.io/mxdavis/pen/KxxmKE by inserting font-size: 20px; to between line 24 and 25 (in the a.upper-text class) and you will see the red border no longer ends at the same point like it does when the font is not adjusted. https://codepen.io/mxdavis/pen/dqqzMy
I need the even sized boxes, and the adjusted font size. Flex seems to be the easiest route since upper-text and lower-text cannot be predicted.
Any advice is greatly appreciated.
Thanks!
Update: I realize now if I play with the text sizes and don't make upper and lower texts equal even my first code snippet doesn't work, which is probably why a font increase is throwing it off. Is there a way to accomplish this or should I just set a fixed height and then click to reveal more? https://codepen.io/mxdavis/pen/KxxedE
I was able to accomplish this (for the most part) using flex and grid together.
I still have to guestimate a max template row for unpredictable text but at least I can guarantee the starting points with this.
https://codepen.io/mxdavis/pen/KxxedE
Here's the new css with the .inner now using display: grid instead of flex.
.outer {
display: flex;
flex-flow: row wrap;
.inner {
border: 5px solid yellow;
display: grid;
grid-template-rows: 210px minmax(max-content, 3fr) minmax(max-content, 2fr) 30px;
grid-row-gap: 5px;
text-align: center;
margin-right: 1em;
margin-bottom: 1.5em;
width: 150px;
font-size: 1.00em;
a.image{
border: 5px solid orange;
img {
width: em(160px);
height: em(210px);
}
}
a.upper-text {
border: 5px solid red;
line-height: normal;
}
.lower-text {
border: 5px solid green;
}
.price {
border: 5px solid blue;
margin: 0;
}
}
}
I still would be interested to see how to rely ONLY on the most content for that row, without using tables.

How to make tab buttons width flexible - ionic 2

Is there any way to make the width of tabs buttons flexible ?
for example this my normal tabs
I want to make the tabs width such as this image
I could show the full text by this css code
.tab-button {
min-width: fit-content;
}
but the result was such as the this picture
Maybe try something like this:
.tabs{
border: 1px solid black;
width: 300px;
display: flex;
justify-content: space-between;
}
.single-tab{
padding: 10px 20px;
border: 1px solid gray;
flex-grow: 1;
}
<div class="tabs">
<div class="single-tab">
Tab1
</div>
<div class="single-tab">
Tab2222222
</div>
<div class="single-tab">
Tab3
</div>
</div>