So I've got this header with three elements in them.
What I want is basically this:
http://jsfiddle.net/zktbfmqo/2/
Only with vertically centered content in each of the divs as well.
Is there an easy and clever way to do this without using absolutes etc?
Vertical-align: middle doesn't seem to do much, but that property isn't always easy to work with either.
HTML:
<div id="container">
<div class="box1">Text</div>
<div class="box2">Text</div>
<div class="box3">Text</div>
<span class="stretch"></span>
</div>
CSS:
#container {
border: 2px dashed #444;
height: 125px;
text-align: justify;
-ms-text-justify: distribute-all-lines;
text-justify: distribute-all-lines;
min-width: 612px;
}
.box1, .box2, .box3 {
width: 150px;
height: 125px;
vertical-align: middle;
display: inline-block;
*display: inline;
zoom: 1;
text-align: center;
}
.stretch {
width: 100%;
display: inline-block;
font-size: 0;
line-height: 0
}
First you can achieve the same result in a better way by using Flexbox.
For vertical align text to the middle you can simply approach that by adding the line-height property and set it to the same exact height of the container div so in your case it would be 125px or if you used flexbox it can be done with align-items: center , and here is the final code:
.wrapper {
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row nowrap; /* Safari 6.1+ */
flex-flow: row nowrap;
-webkit-justify-content: space-between; /* Safari 6.1+ */
justify-content: space-between;
font-weight: bold;
height: 125px;
min-width: 612px;
padding: 5px;
border: 2px dashed #444;
}
.wrapper > div{
display: -webkit-flex;
display: flex;
-webkit-flex-basis: 150px;
flex-basis: 150px;
justify-content: center;
align-items: center;
}
.aside-1, .aside-3{
background: #ccc
}
.aside-2{
background: #0ff;
}
<div class="wrapper">
<div class="aside aside-1">text1</div>
<div class="aside aside-2">text2</div>
<div class="aside aside-3">text3</div>
</div>
Flexbox to the rescue!
Good resources:
https://philipwalton.github.io/solved-by-flexbox/
https://github.com/philipwalton/flexbugs
#container {
display: flex; /* magic maker */
justify-content: space-between; /* set equal space between boxes */
border: 2px dashed #444;
height: 125px;
/* just for demo */
min-width: 612px;
}
.box1, .box2, .box3, .box4 {
display: flex; /* magic maker */
/*
shorthand for flex-grow, flex-shrink, and flex-basis properties
we don't want the boxes to grow or shrink, and the basis is the explicit
width we want them
*/
flex: 0 0 150px;
justify-content: center; /* horizontally center text within */
align-items: center; /* vertically center text within */
height: 125px;
}
.box1, .box3 {
background: #ccc
}
.box2, .box4 {
background: #0ff
}
<div id="container">
<div class="box1">Text</div>
<div class="box2">Text</div>
<div class="box3">Text</div>
</div>
you can use display:table/table-cell and using a workaround with border-collapse/spacing + margin you will get the desired output.
#wrap {
border: 2px dashed #444;
height: 125px;
text-align: justify;
-ms-text-justify: distribute-all-lines;
text-justify: distribute-all-lines;
overflow:hidden;
/* just for demo */
width: 612px;
}
#container {
margin: 0 -81px; /*must be equal to border-spacing */
}
#table {
display: table;
table-layout: fixed;
border-collapse: separate;
border-spacing: 81px 0;
width: 100%;
}
.box1,
.box2,
.box3,
.box4 {
width: 150px;
height: 125px;
vertical-align: middle;
display: table-cell;
text-align: center;
}
.stretch {
width: 100%;
vertical-align: middle;
display: table-cell;
}
.box1,
.box3 {
background: #ccc
}
.box2,
.box4 {
background: #0ff
}
<div id="wrap">
<div id="container">
<div id="table">
<div class="box1">Text</div>
<div class="box2">Text</div>
<div class="box3">Text</div>
<span class="stretch"></span>
</div>
</div>
</div>
Are you familiar with Bootstrap?
It is a CSS Framework made by Twitter.
Put this inside of your head -
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
</head>
Use this in your body to see what it does, there's great docs on it.
<div class="container"> <!-- Creates margin -->
<div class="row"> <!-- Read docs on rows, they're awesome! -->
<div class="col-lg-4"> <!-- 1 -->
<!-- Just to take up space -->
</div>
<div class="col-lg-4"> <!-- 2 -->
<!-- YOUR CONTENT GOES HERE -->
</div>
<div class="col-lg-4"> <!-- 3 -->
<!-- Just to take up space -->
</div>
</div> <!-- ./row -->
</div> <!-- ./container -->
Now inside of the 2nd ./col-lg-4 div all of that content will be perfectly centered in the screen with the text aligned left.
If you want to align center the text, replace
<div class="col-lg-4"> <!-- 2 -->
with
<div class="col-lg-4 text-center"> <!-- 2 -->
Hope this helps!
Related
I want my two buttons, that are actually <a> tags, stick with my input, and be the same size as input. Image perfectly describes what I want to achieve.
Note that I am just starting to learn SASS and CSS. I have tried with this but no luck
NumberInput.js
<div
className="NumberInput"
data-key={dataKey}>
<div className="numberInputField">
<input
data-key={dataKey}
type="text"
name="number"
value={getValue(datakey)}
onChange={onChange(datakey)}/>
</div>
<div className="buttonsField">
<div className="row">
<ValueChangeButton/>
</div>
<div className="row">
<ValueChangeButton/>
</div>
</div>
</div>
NumberInput.scss
$inputMaxWidth: 450px;
$maxHeight: 80px;
$btnFieldMaxWidth: 150px;
.NumberInput{
max-width: $inputMaxWidth;
max-height: $maxHeight;
.numberInputField{
display: inline-block;
text-align: center;
max-width: inherit;
max-height: inherit;
}
.buttonsField{
display: inline-block;
max-width: $btnFieldMaxWidth;
max-height: $maxHeight;
.button{
width: auto;
height: auto;
}
}
}
The result I get is, buttons are contained in their respective rows, but are not the same size as input, and they are flying all around the page. Also, if I change the className of my input, and set the className of its <div> to "numberInputField", it doesn't change its width and height.
Flexbox is perfect for this:
body {
margin: 1em;
}
.NumberInput {
display: flex;
max-width:450px;
margin:auto;
}
.numberInputField {
flex: 3; /* say 3/4 of width */
display: flex;
flex-direction: column;
}
input {
padding: 1em 4em;
flex: 1;
}
.buttonsField {
flex: 1; /* say 1/4 of width */
display: flex;
flex-direction: column;
}
.row {
flex: 1; /* share width equally */
}
a {
width: 100%;
display: block;
background: rebeccapurple;
text-align:center;
text-decoration: none;
font-size: 1.5em;
color: white;
border:1px solid grey;
}
<div class="NumberInput">
<div class="numberInputField">
<input type="submit" />
</div>
<div class="buttonsField">
<div class="row">
↑
</div>
<div class="row">
↓
</div>
</div>
</div>
I've been working on learning flexbox for layout and have been unable to figure out why text is not wrapping inside the flex-item. The text is breaking out of the container like this:
html,
body {
height: 100%;
}
.main {
max-width: 10em;
margin: 1em auto;
}
.flex-row {
display: flex;
align-items: center;
justify-content: center;
min-height: 12em;
border: 1px solid red;
}
.flex-column {
display: flex;
flex-direction: column;
}
.flex-item {
padding: 5px;
border: 1px solid black;
}
<div class="main">
<div class="flex-row">
<div class="flex-column">
<div class="flex-item">
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
</div>
<div class="flex-item">
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
</div>
</div>
</div>
</div>
There are no spaces between your text.
The default value of the word-break property is normal, meaning that a continuous line of text has no line breaks.
For these reasons, your text is not wrapping and overflowing the container.
Add word-break: break-all to .flex-item.
html,
body {
height: 100%;
}
.main {
max-width: 10em;
margin: 1em auto;
}
.flex-row {
display: flex;
align-items: center;
justify-content: center;
min-height: 12em;
border: 1px solid red;
}
.flex-column {
display: flex;
flex-direction: column;
}
.flex-item {
padding: 5px;
border: 1px solid black;
word-break: break-all; /* new */
}
<div class="main">
<div class="flex-row">
<div class="flex-column">
<div class="flex-item">
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
</div>
<div class="flex-item">
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
</div>
</div>
</div>
</div>
From MDN:
word-break
The word-break CSS property specifies whether or not the browser
should insert line breaks wherever the text would otherwise overflow
its content box.
In contrast to overflow-wrap, word-break will create a break at
the exact place where text would otherwise overflow its container
(even if putting an entire word on its own line would negate the need
for a break).
Values
normal
Use the default line break rule.
break-all
To prevent overflow, word breaks should be inserted between any two
characters (excluding Chinese/Japanese/Korean text).
keep-all
Word breaks should not be used for Chinese/Japanese/Korean (CJK) text.
Non-CJK text behavior is the same as for normal.
There's actually another reason – flexbox-specific – why the flex items are overflowing the container. Here's the explanation:
Why doesn't flex item shrink past content size?
To contain the items (without the need for the text to wrap), you could apply min-width: 0, overflow: hidden or overflow: auto to .flex-column.
html,
body {
height: 100%;
}
.main {
max-width: 10em;
margin: 1em auto;
}
.flex-row {
display: flex;
align-items: center;
justify-content: center;
min-height: 12em;
border: 1px solid red;
}
.flex-column {
display: flex;
flex-direction: column;
overflow: hidden; /* new */
/* overflow: auto; */
/* min-width: 0; */
}
.flex-item {
padding: 5px;
border: 1px solid black;
}
<div class="main">
<div class="flex-row">
<div class="flex-column">
<div class="flex-item">
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
</div>
<div class="flex-item">
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
</div>
</div>
</div>
</div>
I am trying to make a DIV fill its whole parent container with pure CSS. height:100% doesn't do it and flexbox or display:table on the parent also didn't help :(
In the attached code, we're talking about the innermost
div.CodeMirror
The problem occurs in the latest Safari on MacOS. In Chrome all is fine.
html, body, #root {
margin: 0;
padding: 0;
height: 100%;
}
.App {
display: flex;
flex-flow: column;
height: 100%;
}
div.editorContainer {
flex: 1 1 auto;
display: flex;
margin-bottom: 1em;
}
div.ReactCodeMirror {
padding: 5px;
width: 100%;
background-color: #ddf;
}
.CodeMirror {
height: 100%;
border: 1px solid #ccc;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<div id="root">
<div class="App">
<nav class="navbar navbar-default"></nav>
<div class="editorContainer">
<div style="background-color: #aaf; width: 160px;">Side bar</div>
<div class="ReactCodeMirror">
<div class="CodeMirror">Should fill light blue area</div>
</div>
</div>
</div>
</div>
First off, something is wrong with the class declaration of CodeMirror, according to your code, it requires the div to contain a subclass of cm-s-robocom, i.e:
<div class="CodeMirror cm-s-robocom">Should fill light blue area</div>
If you want this css declaration to have either .CodeMirror or .cm-s-robocom, you should use a comma between:
.CodeMirror, .cm-s-robocom {height: 100%; border: 1px solid #ccc;}
What fixed it for me in safari was adding height: 100% to both editorContainer and ReactCodeMirror:
div.editorContainer {flex: 1 1 auto; display: flex; margin-bottom: 1em;height:100%;}
div.ReactCodeMirror {padding: 5px; width: 100%; background-color: #ddf;height:100%;}
So the final snippet is - I think you should also add height 100% on the side-bar to make it appear ok:
html, body, #root {margin: 0; padding: 0; height: 100%; }
.App {display: flex; flex-flow: column; height: 100%; }
div.editorContainer {flex: 1 1 auto; display: flex; margin-bottom: 1em;}
div.ReactCodeMirror {padding: 5px; width: 100%; background-color: #ddf; display: flex; flex: 1 1; }
.CodeMirror {border: 1px solid #ccc; display: flex; flex: 1 1; }
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<div id="root">
<div class="App">
<nav class="navbar navbar-default"></nav>
<div class="editorContainer">
<div style="background-color: #aaf; width: 160px; top: 0; bottom: 0; position: relative;">Side bar</div>
<div class="ReactCodeMirror">
<div class="CodeMirror">Should fill light blue area</div>
</div>
</div>
</div>
</div>
Just add height: 100% on .CodeMirror (bug in Safari causes this to not work properly)
So you will need to add display: flex to the .CodeMirror parent, flex: 1 to the child.
html, body, #root {margin: 0; padding: 0; height: 100%; }
.App {display: flex; flex-flow: column; height: 100%; }
div.editorContainer {flex: 1 1 auto; display: flex; margin-bottom: 1em;}
div.ReactCodeMirror {padding: 5px; width: 100%; background-color: #ddf; display: flex;}
.CodeMirror {border: 1px solid #ccc; flex: 1;}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<div id="root">
<div class="App">
<nav class="navbar navbar-default"></nav>
<div class="editorContainer">
<div style="background-color: #aaf; width: 160px;">Side bar</div>
<div class="ReactCodeMirror">
<div class="CodeMirror">Should fill light blue area</div>
</div>
</div>
</div>
</div>
This should work
div.CodeMirror{height: 100%;}
I have a vertically central adaptable scrollable flexbox element, which itself should have two columns (I solved this with two child-divs). The central flexbox should have a frame and a central divider line.
I can't get the central divider line to run all the way to the bottom of the scrollable flexbox. I tried it with a third child div element but the line only appears for the vertical extent of the flexbox.
How can I make two columns in a scrollable flexbox with a frame and central divider line running all the way to the bottom?
Thank you for your help.
Here is the example:
https://jsfiddle.net/soliman/0d0tn22x/2/
<body>
<div class="wrapper">
<div class="header">
<h1>Header</h1>
</div>
<div class="content">
<div class="leftContent"> Column 1
With a lot of lines.
</div>
<div class="divider"></div>
<div class="rightContent"> Column 2
With fewer lines
</div>
</div>
<div class="footer">
Footer
</div>
</div>
</body>
CSS:
html,
body {
height: 100%;
margin: 0;
padding: 0;
background: black;
color: red;
}
.wrapper {
display: flex;
/* use the flex model */
height: 100%;
flex-direction: column;
}
.header {
margin: 1em 1em 0 1em;
}
.content {
flex: 1 1 auto;
display: flex;
overflow-y: auto;
position: relative;
min-height: 100px;
margin: 0 1em 0 1em;
border: 6px double red;
}
.content > div {
width: 50%;
padding: 3%;
}
.content > div:first-child {
margin-right: 10px;
}
.footer {
margin: 0 1em 1em 1em;
}
.divider {
position: absolute;
left: 50%;
top: 0%;
bottom: 0%;
border-left: 6px double red;
}
Try this mixed flexbox and CSS table layout. You can set the content area as a table, and the three columns as table cells, so they always be equal height.
There is one issue with the approach is - it only works properly if the content is taller than the container, otherwise the vertical line will stop in the middle. See the other approach at the bottom.
jsFiddle
html,
body {
height: 100%;
margin: 0;
}
.wrapper {
height: 100%;
display: flex;
flex-direction: column;
}
.content {
flex: 1;
overflow-y: auto;
min-height: 100px;
border: 1px solid;
}
.wrapContent {
display: table;
width: 100%;
}
.wrapContent > div {
display: table-cell;
}
.leftContent,
.rightContent {
width: 50%;
}
.divider {
border-left: 1px solid;
}
<div class="wrapper">
<div class="header">
<h1>Header</h1>
</div>
<div class="content">
<div class="wrapContent">
<div class="leftContent">
<div style="height:500px;">Left</div>
</div>
<div class="divider"></div>
<div class="rightContent">
<div style="height:auto;">Right</div>
</div>
</div>
</div>
<div class="footer">
<p>Footer</p>
</div>
</div>
Another way would be using background image for the vertical line, set that to the center of the content container, with repeat-y, the image can be just a square dot. It works well even if the content is shorter than the container.
jsFiddle
html,
body {
height: 100%;
margin: 0;
}
.wrapper {
height: 100%;
display: flex;
flex-direction: column;
}
.content {
flex: 1;
display: flex;
overflow-y: auto;
min-height: 100px;
border: 1px solid;
background: url("http://i.imgur.com/oyQ4xsL.png") center top repeat-y;
background-size: 1px;
}
.leftContent,
.rightContent {
width: 50%;
}
<div class="wrapper">
<div class="header">
<h1>Header</h1>
</div>
<div class="content">
<div class="leftContent">
<div style="height:500px;">left</div>
</div>
<div class="rightContent">
<div style="height:auto;">right</div>
</div>
</div>
<div class="footer">
<p>Footer</p>
</div>
</div>
My question is simple. Is it possible to have display: table on a flex item?
When I set it on an item, the layout doesn't work as expected - the second flex item doesn't grab the available vertical/horizontal space.
.parent {
min-height: 200px;
border: 1px solid black;
display: flex;
flex-direction: column;
text-align: center;
}
.header {
background-color: gray;
}
.content {
flex: 1;
display: table;
background-color: red;
}
.content > span {
display: table-cell;
vertical-align: middle;
}
<div class="parent">
<div class="header">
<span>Header</span>
</div>
<div class="content">
<span>Main content</span>
</div>
</div>
Of course you can, but not necessarily a good solution though.
May I suggest you use flex all the way.
.parent {
min-height: 200px;
border: 1px solid black;
display: flex;
flex-direction: column;
text-align: center;
}
.header {
background-color: gray;
}
.content {
flex: 1;
background-color: red;
display: flex;
align-items: center;
justify-content: center;
}
<div class="parent">
<div class="header">
<span>Header</span>
</div>
<div class="content">
<span>Main content</span>
</div>
</div>
Side note:
A table element is special and doesn't behave as normal block or inline elements. To make it work with display: table, you need to set a height to your parent as well as to the table, like in this sample, http://jsfiddle.net/LGSon/0bzewkf4.
Still, as you can see, the table height is 200px because flex has some flaws when it comes to limit height's, so it is not display:table that breaks your flex, it is flex who is somewhat broken.
Here is another answer of mine, showing yet another workaround where flex doesn't behave: Normalizing Flexbox overflow in IE11
It's a big question why you use table in flexbox...
But you can set width to your table and inherit min-height from parent
.parent {
min-height: 200px;
border: 1px solid black;
display: flex;
flex-direction: column;
text-align: center;
}
.header {
background-color: gray;
}
.content {
display: table;
flex:1;
background-color: red;
width:100%;
min-height:inherit;
}
.content > span {
display: table-cell;
vertical-align: middle;
height: 100%;
}
<div class="parent">
<div class="header">
<span>Header</span>
</div>
<div class="content">
<span>Main content</span>
</div>
</div>
You should not need to use a table layout at all here. Just add align-self: center; to .content- > span {.... And make the span element become a flex item as well, by adding display:flex to the .content element. The reason why the table layout is not working for you is because vertcal-align has no effect on the alignment of flex items. So mixing a flex-layout with a table-layout by changing the display property of a flex-item seems not to be a good idea, because you are loosing the flexibility of the flex-layout.
Properties not affecting flexible boxes
Because flexible boxes use a different layout algorithm, some properties do not make sense on a flex container:
column-* properties of the multiple column module have no effect on a flex item.
float and clear have no effect on a flex item. Using float causes the display property of the element to compute to block.
vertical-align has no effect on the alignment of flex items.
.parent {
min-height: 200px;
border: 1px solid black;
display: flex;
flex-direction: column;
text-align: center;
}
.header {
background-color: gray;
}
.content {
flex: 1;
display: flex;
background-color: red;
}
.content > span {
flex: 1;
align-self: center;
}
<div class="parent">
<div class="header">
<span>Header</span>
</div>
<div class="content">
<span>Main content</span>
</div>
</div>
Tables are row or horizontally oriented so wouldn't you get weird results if placed within a flex-column? I changed everything to a good old block, they stack very well in a column flow--vertical harmony.
.content is dead center by using: position: relative; top: 50%; and translateY(360%); for vertical and text-align: center; for horizontal. Oh and of course turning that span into a useful block.
Changed the following:
.content {
flex: 1;
background-color: red;
}
.content > span {
display: block;
position: relative;
top: 50%;
transform: translateY(360%);
text-align: center;
}
I changed display: table to table-row is this what you wanted?
.parent {
min-height: 200px;
border: 1px solid black;
display: flex;
flex-direction: column;
text-align: center;
}
.header {
background-color: gray;
}
.content {
flex: 1;
background-color: red;
}
.content > span {
display: block;
position: relative;
top: 50%;
transform: translateY(360%);
text-align: center;
}
<div class="parent">
<div class="header">
<span>Header</span>
</div>
<div class="content">
<span>Main content</span>
</div>
</div>