Prevent contenteditable (in flexed div) from expanding [duplicate] - css

This question already has answers here:
Why don't flex items shrink past content size?
(5 answers)
Closed 5 years ago.
I'm starting with css flex and I have a hard time with using a contenteditable that I can't prevent from expanding horizontally when the text is too long.
I tried on:
- Chrome
- Firefox
- Opera
- Safari
They all make the divs expand but Safari, who does what I expect.
Here is the HTML:
<div class="container">
<div class="column">
<div class="field">
<div class="field_left"></div>
<div class="field_middle" contenteditable="true"></div>
<div class="field_right"></div>
</div>
</div>
<div class="column">
<div class="field">
<div class="field_left"></div>
<div class="field_middle" contenteditable="true"></div>
<div class="field_right"></div>
</div>
</div>
<div class="column">
<div class="field">
<div class="field_left"></div>
<div class="field_middle" contenteditable="true"></div>
<div class="field_right"></div>
</div>
</div>
<div class="column">
<div class="field">
<div class="field_left"></div>
<div class="field_middle" contenteditable="true"></div>
<div class="field_right"></div>
</div>
</div>
</div>
Here is the CSS:
.container
{
width: calc(100% - 34px);
height:185px;
margin-left:17px;
margin-top:17px;
display:flex;
}
.column{
flex:1;
height:186px;
margin-right:1.75%;
}
.column:nth-child(5){
margin-right:0px;
}
.field{
margin-bottom:5px;
display:flex;
width:100%;
}
.field_left{
width:6px;
height:24px;
background:green;
}
.field_middle{
height:24px;
background:red;
width:calc(100% - 13px);
}
.field_right{
width:7px;
height:24px;
background:blue;
}
[contenteditable]
{
display:inline;
white-space: nowrap;
overflow:hidden;
text-overflow: inherit;
-webkit-user-select: auto;
user-select: auto;
-moz-user-select: -moz-text;
}
Of course, the HTML could be less complicated for such a result (divs into divs into divs) but keep in mind that I cleaned the code as much as possible in order to present it to you as the design asks for this.
However, I decided to show the relevant part of structure as it might be important to fix the problem.
Here is a JSFiddle of the result:
https://jsfiddle.net/b4er9tLg/2/
If you type a text into one of these boxes, when the text is long enough, it will expand its containing div and change the overall layout of the page.
(if it doesn't do that on your browser, then your browser is one of the happy few).
Basically, what I need is to get something like a hidden overflow on all browsers of text written so that the overall design won't break.
I just can't get it to work.
Thanks for your help.

You have given .column the property flex: 1. From the spec
w3
flex: <positive-number>
Equivalent to flex: <positive-number> 1 0. Makes the flex item flexible and sets the flex basis to zero, resulting in an item that
receives the specified proportion of the free space in the flex
container. If all items in the flex container use this pattern, their
sizes will be proportional to the specified flex factor.
To prevent column and it's contents from expanding you need to give it a max-width value.
I would also suggesting removing margin-right from .column. Instead, set the column width and use the justify-content property on the container.
fiddle
.container {
width: calc(100% - 34px);
height: 185px;
margin-left: 17px;
margin-top: 17px;
display: flex;
justify-content: space-between;
}
.column {
flex: 1;
height: 186px;
max-width: 19%;
}
.field {
margin-bottom: 5px;
display: flex;
width: 100%;
}
.field_left {
width: 6px;
height: 24px;
background: green;
}
.field_middle {
height: 24px;
background: red;
width: calc(100% - 13px);
}
.field_right {
width: 7px;
height: 24px;
background: blue;
}
[contenteditable] {
display: inline;
white-space: nowrap;
overflow: hidden;
text-overflow: inherit;
-webkit-user-select: auto;
user-select: auto;
-moz-user-select: -moz-text;
}
<div class="container">
<div class="column">
<div class="field">
<div class="field_left"></div>
<div class="field_middle" contenteditable="true"></div>
<div class="field_right"></div>
</div>
</div>
<div class="column">
<div class="field">
<div class="field_left"></div>
<div class="field_middle" contenteditable="true"></div>
<div class="field_right"></div>
</div>
</div>
<div class="column">
<div class="field">
<div class="field_left"></div>
<div class="field_middle" contenteditable="true"></div>
<div class="field_right"></div>
</div>
</div>
<div class="column">
<div class="field">
<div class="field_left"></div>
<div class="field_middle" contenteditable="true"></div>
<div class="field_right"></div>
</div>
</div>
<div class="column">
<div class="field">
<div class="field_left"></div>
<div class="field_middle" contenteditable="true"></div>
<div class="field_right"></div>
</div>
</div>
</div>

Related

How to make resizable grids based on number of items?

I am working on a questionnaire design, which can have one or more answers, something like this:
This looks alright for 3 or more answers as in the above screenshot. However, when there's a single or couple of answers, they are taking too much space, resulting in this:
How can I make the boxes smaller if there are fewer answers, still making them look good, i.e. centered and with proper spacing, etc.?
Here's a working code sandbox where you can see what I have so far.
Maybe you may need a different approach with only flexbox
/* custom class */
.box {
display: inline-flex;
align-items: center;
justify-content: center;
width: 150px;
height: 150px;
border: 2px solid black;
margin: 2px;
}
/* responsivity class */
.responsive {
width: 100%;
display: flex;
margin: 0 auto;
}
.center-placer {
width: max-content;
margin: 0 auto;
}
<div class="responsive">
<div class="center-placer">
<div class="box">
A
</div>
<div class="box">
B
</div>
<div class="box">
C
</div>
<div class="box">
D
</div>
<div class="box">
E
</div>
</div>
</div>
<div class="responsive">
<div class="center-placer">
<div class="box">
A
</div>
<div class="box">
B
</div>
</div>
</div>
<div class="responsive">
<div class="center-placer">
<div class="box">
C
</div>
</div>
</div>

How can I have auto-width content in flexbox without destroying the layout? (take as much space as necessary and as little space as possible)

I have an example on JSFiddle on how I want to solve my issue with flexbox: I want the left column to fit the width accordingly to the content - break a line if the text is too long. Unfortunately it always takes as little space as possible, which results in breaking the layout.
I have a fiddle below, first you see two blocks with how it looks now, below you see 2 blocks how I want it to look like (I've defined fixed width for visual reasons, but I want it to be dynamically with flexbox, obviously).
I'm pretty sure I can do this easily but I can't see the wood for the trees. Any kind of help is highly appreciated :)
.flex {
display: flex;
background: #333;
max-width: 380px;
}
.first {
flex: 0;
background: #666;
}
.second {
flex: 1;
background: #999;
}
<p>How it looks like with my flexbox approach</p>
<div class="flex">
<div class="first">
Here is my Dynamic Text
</div>
<div class="second">
Next to Text
</div>
</div>
<br />
<div class="flex">
<div class="first">
Here is my Dynamic Text Here is my Dynamic Text
</div>
<div class="second">
Next to Text
</div>
</div>
<hr />
<p>How it should look like</p>
<!-- Ignore all code below, please - everything below is just here for visual reasons -->
<div>
<div style="background: #666; width: 165px; float: left;">Here is my Dynamic Text</div>
<div style="background: #999; float: left;">Next to text</div>
</div>
<div style="clear: both; height: 10px;">
</div>
<div>
<div style="background: #666; width: 302px; float: left;">Here is my Dynamic Text Here is my Dynamic Text</div>
<div style="background: #999;float: left; height: 36px;">Next to text</div>
</div>
Use white-space:nowrap on the second element so it does not collapse.
.flex {
display: flex;
border: 1px solid green;
}
.first {
background: lightblue;
border: 1px solid grey;
}
.second {
white-space: nowrap;
background: lightgreen
}
.narrow {
width: 50%;
<div class="flex">
<div class="first">
Here is my Dynamic Text
</div>
<div class="second">
Next to Text
</div>
</div>
<hr/>
<div class="flex narrow">
<div class="first">
Here is my Dynamic Text Here is my Dynamic Text
</div>
<div class="second">
Next to Text
</div>
</div>

CSS Rule for the 8th and on element in a div

Is it possible to create a CSS rule that applies to the every element except for the first 8 elements? Ie, the 8th plus elements should have a margin top of 65px.
My below less code applies margins to every odd and even button within a menu. Now I want to add a specific margin to the 8th plus buttons. And then ideally apply a specific margin to the 16th plus buttons and so on.
.foo-menu {
.foo-menu-btn {
float: left;
margin: 1px;
}
// Apply specific margin to every second(even) button
.foo-menu-btn:nth-child(even) {
margin-left: -23px;
margin-top: 46px;
}
// Apply specific margin to every odd button
.foo-menu-btn:nth-child(odd) {
margin-left: -23px;
}
// For every button after the 8th one; apply a specific margin
.foo-menu-btn:nth-child( ??? ) {
margin-top: 65px;
}
}
<div class="foo-menu">
<div class="foo-menu-btn"></div>
<div class="foo-menu-btn"></div>
<div class="foo-menu-btn"></div>
<div class="foo-menu-btn"></div>
<div class="foo-menu-btn"></div>
<div class="foo-menu-btn"></div>
<div class="foo-menu-btn"></div>
<div class="foo-menu-btn"></div>
<!-- Now every foo-menu-btn should have a top margin of 65px -->
<div class="foo-menu-btn"></div>
<div class="foo-menu-btn"></div>
<div class="foo-menu-btn"></div>
<div class="foo-menu-btn"></div>
<div class="foo-menu-btn"></div>
<div class="foo-menu-btn"></div>
<div class="foo-menu-btn"></div>
<div class="foo-menu-btn"></div>
</div>
Try below code, i think help full to you.
hr {
display: block; float: left;
width: 50px; height: 50px;
border: solid 2px #aaa; margin: 10px;
}
hr:nth-child(n+9):not(:nth-last-child(-n)) {
background-color: #ddd;
}
<div id=t>
<hr>
<hr>
<hr>
<hr>
<hr>
<hr>
<hr>
<hr>
<hr>
<hr>
<hr>
<hr>
<hr>
<hr>
<hr>
<hr>
<hr>
</div>
You can use the native CSS :nth-child pseudo-class to specify a range. According to the case you specified it might look like this:
div.foo-menu div.foo-menu-btn:nth-child(n+8):nth-child(-n+15) {
margin-left: 50px
}
The downside is that you still have to manually define each range.
To select everything other than the first 8 divs you can use .foo-menu-btn:nth-child(n+9). See it applied to your HTML below (I took out the negative margins so that the divs would be visible for this example):
.foo-menu-btn {
float: left;
margin: 1px;
background-color: #ccc;
height: 1rem;
}
.foo-menu-btn:nth-child(even) {
margin-top: 46px;
}
.foo-menu-btn:nth-child(n+9) {
margin-top: 65px;
}
<div class="foo-menu">
<div class="foo-menu-btn">1</div>
<div class="foo-menu-btn">2</div>
<div class="foo-menu-btn">3</div>
<div class="foo-menu-btn">4</div>
<div class="foo-menu-btn">5</div>
<div class="foo-menu-btn">6</div>
<div class="foo-menu-btn">7</div>
<div class="foo-menu-btn">8</div>
<!-- Now every foo-menu-btn should have a top margin of 65px -->
<div class="foo-menu-btn">9</div>
<div class="foo-menu-btn">10</div>
<div class="foo-menu-btn">11</div>
<div class="foo-menu-btn">12</div>
<div class="foo-menu-btn">13</div>
<div class="foo-menu-btn">14</div>
<div class="foo-menu-btn">15</div>
<div class="foo-menu-btn">16</div>
</div>
Use :
.foo-menu .foo-menu-btn:nth-child(n+9){
color: blue;
}
.foo-menu .foo-menu-btn:nth-child(odd){
color: red;
}
.foo-menu .foo-menu-btn:nth-child(even){
color: green;
}
.foo-menu .foo-menu-btn:nth-child(n+9){
color: blue;
}
<div class="foo-menu">
<div class="foo-menu-btn">1</div>
<div class="foo-menu-btn">2</div>
<div class="foo-menu-btn">3</div>
<div class="foo-menu-btn">4</div>
<div class="foo-menu-btn">5</div>
<div class="foo-menu-btn">6</div>
<div class="foo-menu-btn">7</div>
<div class="foo-menu-btn">8</div>
<!-- Now every foo-menu-btn should have a top margin of 65px -->
<div class="foo-menu-btn">9</div>
<div class="foo-menu-btn">10</div>
<div class="foo-menu-btn">11</div>
<div class="foo-menu-btn">12</div>
<div class="foo-menu-btn">13</div>
<div class="foo-menu-btn">14</div>
<div class="foo-menu-btn">15</div>
<div class="foo-menu-btn">16</div>
</div>

Have div take up 1/6th of remaining parent div height

I am attempting to make a simple calendar using css.
I have a parent div that will contain the calendar, and I have a div within that that contains the header with "Monday", "Tuesday", etc and is of fixed height. I now want to add divs that represent the rows of the calendar and split the remaining space into six even rows. However, I can't figure out how to divide the REMAINING space into 6 parts. Everything I try makes the div 1/6th of the parent div.
Any tips would be appreciated.
HTML:
<div id="parent>
<div id="header">
ST
</div>
<div class="row">
hi
</div>
</div>
CSS:
.row{
width:100%;
height: 16.66%;
background-color:red;
}
When you want to distribute remaining space left by a flexible element, flexbox is the answer.
html, body, #parent {
margin: 0;
height: 100%;
}
#parent {
display: flex;
flex-direction: column;
}
#header {
background-color: green;
}
.row {
width: 100%;
flex: 1; /* Distribute remaining space equally among the rows */
background-color: red;
}
.row:nth-child(odd) {
background-color: blue;
}
<div id="parent">
<div id="header">Header</div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
</div>
There are several ways to do that, and to pick one I need to know more how it should be used.
This sample simply use CSS calc() and subtract 1/6 of the header from 1/6 of the parent.
html, body {
margin: 0;
}
#parent {
height: 100vh;
}
#header {
height: 60px;
background-color:green;
}
.row{
height: calc(16.66% - 10px);
background-color:red;
}
.row:nth-child(odd){
background-color:blue;
}
<div id="parent">
<div id="header">
Header
</div>
<div class="row">
</div>
<div class="row">
</div>
<div class="row">
</div>
<div class="row">
</div>
<div class="row">
</div>
<div class="row">
</div>
</div>

Child element shifting parent div

I've searched quite a bit looking for an explanation as to why this behavior is occurring.
Essentially I've setup 2 columns, each with a nav bar and content area.
CSS
#mainContainer {
background-color: lightblue;
width: 100%;
height: 300px;
}
#leftContainer, #rightContainer {
border: 1px solid black;
display: inline-block;
background-color: red;
width: 40%;
height: 100%;
}
#leftBar, #rightBar {
background-color: purple;
height: 10%;
}
#leftMain, #rightMain {
background-color: grey;
height: 90%;
}
HTML
<div id="mainContainer">
<div id="leftContainer">
<div id="leftBar"></div>
<div id="leftMain"></div>
</div>
<div id="rightContainer">
<div id="rightBar"></div>
<div id="rightMain"></div>
</div>
</div>
Whenever I add an element to the nav bar in only one column it shifts the entire column down.
http://jsfiddle.net/qn6rs0q2/3/
<div id="mainContainer">
<div id="leftContainer">
<div id="leftBar">
<button>Test</button>
</div>
<div id="leftMain"></div>
</div>
<div id="rightContainer">
<div id="rightBar"></div>
<div id="rightMain"></div>
</div>
</div>
But if I add another element to the other column they line up again.
http://jsfiddle.net/qn6rs0q2/5/
<div id="mainContainer">
<div id="leftContainer">
<div id="leftBar">
<button>Test</button>
</div>
<div id="leftMain"></div>
</div>
<div id="rightContainer">
<div id="rightBar">
<button>Test 2</button>
</div>
<div id="rightMain"></div>
</div>
</div>
To clarify, I'm not looking for a solution to fix this behavior. Rather I'm hoping someone can explain the underlying reason behind why it's behaving as it is. Thanks in advance.
It happens because the default vertical alignment of inline elements is the baseline. If you set the vertical alignment to top (or middle) for both sides, they line up as you want:
#leftContainer, #rightContainer {
border: 1px solid black;
display: inline-block;
background-color: red;
width: 40%;
height: 100%;
vertical-align:top;
}
jsFiddle example

Resources