I'm working on a project where there is a row of controls, each of which is a button element. There is content inside of the buttons, and they are laid out in a row with flexbox. The button element centers its content vertically, and I can't figure out how to override it to vertically align it at the top of the button. The controls all need to be the same height and same width, and clicking anywhere in the borders must count as a click on the button.
This Codepen shows the problem clearly: http://codepen.io/anon/pen/RPpqdz
.wrapper {
display: flex;
flex-direction: row;
width: 80%;
}
button,
.object {
font-family: sans-serif;
font-size: 1em;
padding: 1em;
background: #fff;
flex: 1;
border: 1px solid red;
text-align: left;
}
<h1>What it looks like</h1>
<div class="wrapper">
<button>I am Content</button>
<button>I am Much Longer Content That Goes Here and Here</button>
<button>I am Content</button>
</div>
<h1>What I want it to look like</h1>
<div class="wrapper">
<div class="object">I am Content</div>
<div class="object">I am Much Longer Content That Goes Here and Here</div>
<div class="object">I am Content</div>
</div>
I realize this issue could be solved by not using button elements, but I also feel like I SHOULD be able to override this behavior of button elements. I'd like to figure this out for my own sanity!
Firstly, having h2 and p inside button is not valid HTML.
Secondly, there is no simple way to control the position of elements in a button, especially vertically.
But if you really really must use this BROKEN HTML, and only the top alignment is important, you can force the elements to take up fixed heights so that the button will align them at the top, like so:
button > h2 {
height: 48px;
}
button > p {
height: 16px;
}
I must say this is still not exactly the same as using <div>, so I don't know if this is sufficient.
In any case, do seriously try to convince those in charge of the "larger context of the project" to use proper valid HTML.
Edit:
If only inline elements are used inside the button, the problem becomes more manageable. The only caveat is: you need to know beforehand the height of the button. You can then simulate top-bottom flow using paddings.
button {
padding-top: 1em;
padding-right: 1em;
padding-bottom: 5em; /* make sure bottom + top padding == height */
padding-left: 1em;
height: 6em;
}
Still probably not ideal - feels like a heavily plastered hack solution.
*I'm not sure what do you want and what do you mean by "how to override it to vertically align it at the top of the button?"? but I hope this code is what you want.(same height, width and even with spaces also buttons matching with div (.objects).
.wrapper {
display: inline-flex;
display: -moz-inline-box;
width: 90%;
}
button, .object {
font-family: sans-serif;
font-size: 1em;
padding: 1em;
background: #fff;
border: 1px solid red;
text-align: left;
margin: 0em 0.3em 0em 0em;
}
Related
I am looking for some direction pointing as I am a bit lost.
I have a container div with a :before style I am using to add some information on a page. This works well as I found an example using SO at How can I add a large faded text background via css?. What I want is that when the "main" div is expanded, that it covers up the :before pseudo element's content.
I have tried various combinations of div structuring (containers) and palyed with the z-index of the pseudo element and the main div. NOTE that I can not put a "z-index" of -1 on the "title" text ... as that actually hides it behind content I actually want to see in my actual application.
HTML
<div class="show-title" data-div-title="Div Title">
<div class="center-me">
This is my box!
</div
<div>
<button id="set500">500px</button>
<button id="set1000">1000px</button>
<button id="set1500">1500px</button>
CSS
.show-title::before {
color: dimgrey;
content: attr(data-div-title);
display: block;
font-size: 1.2em;
line-height: 1;
position: absolute;
top: 10px;
left: 10px;
-ms-writing-mode: vertical-lr;
writing-mode: vertical-lr;
text-orientation: upright;
padding: 3px;
background-color: gainsboro;
border: 1px solid darkgray;
border-radius: 3px;
z-index:1;
}
.center-me {
color: dimgrey;
padding:10px;
background-color: gainsboro;
border: 1px solid maroon;
width: 500px;
height: 300px;
margin-left: auto ;
margin-right: auto ;
overflow: auto;
z-index:10;
}
JavaScript (just for enlarging the main content div, not apart of the actual question!)
(function($){
$("#set500").on("click", function() {
$(".center-me").width("500px");
})
$("#set1000").on("click", function() {
$(".center-me").width("1000px");
})
$("#set1500").on("click", function() {
$(".center-me").width("1500px");
})
})(jQuery);
I created a little jsFiddle to show what I am referring to. When the "box" is expanded, I would like it to go "over" (basically hiding) any of the "Title" text. (Any little bit left over showing is fine!)
http://jsfiddle.net/uLohn3e4/3/
Any direction pointing would be useful as I just could not find what I was trying to accomplish. Even if that is to try a new layout altogether (that achieves something similar). If I am missing any useful information, please ask ... thanks in advance.
Simply add position:relative; to your .center-me element
in order for your z-index to apply z-index#MDN.
http://jsfiddle.net/uLohn3e4/5/
Alright, so I'm trying to make a line of different text bits in html/css. This will be the precursor for a navbar. My HTML is:
<div id="navBar">
<p class="navBartext">About</p>
<p class= "navbartext">News</p>
<p class= "navbartext">Contact Us</p>
<p class= "navbartext">Jobs</p>
</div>
and the CSS:
.navBartext{
text-align: center;
color:black;
font-size: 20;
font-family: 'Poiret One', cursive;
display: inline;
padding-right: 20px;
}
#navbar{
width: 100%;
height: 50px;
}
Now, when I take the "display: inline;" out of the code, the text aligns vertically instead of horizontally, and then I can use text align to position it, but I want them all in one line. When I use display-inline though it seems to completely circumvent the text-align function (as anything put in here will be ignored). Is there something I'm missing? Perhaps I just don't know enough about the display function.
If you want to align the words horizontally, you have to use display:inline-block; so that the elements will be treated as text. Always use inline-block for the child elements and text-align:center; for the parent.
p{
color:black;
font-size: 20;
font-family: 'Poiret One', cursive;
display: inline-block;
padding-right: 20px;
}
#navbar{
width: 100%;
height: 50px;
text-align:center;
}
VIEW DEMO
Try this, you can use <ul> element instead of div, div is better as a wrapper if u need wrap navBar:
[http://jsfiddle.net/WT7qv][1]
http://jsfiddle.net/WT7qv
I'm trying create a balanced (2-) column-layout.
The content is not text but blocks and varies in height.
The content should be placed alternatingly left and right, as long as "left" and "right" have (roughly) the same height..
I.e. in this image:
The space between 1 and 3's shouldn't be there.
Or in this image:
the 2's should stand alone on the right side and the 1, 3's and 4 should stand on the left side (without space between them).
I tried using "floating <li>'s" like this:
HTML:
<ol class="context">
<li class="gruppe">1</li>
<li class="gruppe">2.0<br />2.1</li>
<li class="gruppe">3.0<br />3.1</li>
<li class="gruppe">4</li>
</ol>
CSS:
ol.context
{
border: 1px solid #048;
list-style: none;
margin: 0;
padding: 0 0 8px 0;
overflow: auto;
}
li.gruppe
{
background: #048;
color: white;
float: left;
font: bold 32px Arial, sans-serif;
margin: 1px;
text-align: center;
width: calc(50% - 2px);
}
(See attempt 1 and attempt 2)
I have also tried to use column's (column-count: 2; column-fill: auto;) but this does not fill the columns left-to-right first. (It fills top-to-bottom first.)
Is this even possible without JavaScript?
I would say this is not possible without JS. Here is a fiddle I made based on an article from Ben Holland. At least to me looks like what you are after.
http://jsfiddle.net/QWsBJ/2/
HTML:
<body onload="setupBlocks();">
<div class="block">
<p>***Content***</p>
</div>
<div class="block">
<p>***Content***</p>
</div>
<div class="block">
<p>***Content***</p>
</div>
<div class="block">
<p>***Content***</p>
</div>
<div class="block">
<p>***Content***</p>
</div>
</body>
CSS:
.block {
position: absolute;
background: #eee;
padding: 20px;
width: 300px;
border: 1px solid #ddd;
}
JS:
var colCount = 0;
var colWidth = 0;
var margin = 20;
var blocks = [];
$(function(){
$(window).resize(setupBlocks);
});
function setupBlocks() {
colWidth = $('.block').outerWidth();
colCount = 2
for(var i=0;i<colCount;i++){
blocks.push(margin);
}
positionBlocks();
}
function positionBlocks() {
$('.block').each(function(){
var min = Array.min(blocks);
var index = $.inArray(min, blocks);
var leftPos = margin+(index*(colWidth+margin));
$(this).css({
'left':leftPos+'px',
'top':min+'px'
});
blocks[index] = min+$(this).outerHeight()+margin;
});
}
Array.min = function(array) {
return Math.min.apply(Math, array);
};
Updated: I believe this is almost impossible to achieve with CSS only. There are many different solutions, but they all require some compromises unless you are willing to use JavaScript or some server-side code.
Using CSS columns
Here's an alternate fiddle using reordered blocks. Here's a fiddle demo using CSS columns without reordering.
You can use CSS colunms to change your block flow to vertical unless you alter the order of their output. If you can output odd numbers first, then even numbers, you win.
<div class="wrapper">
<div class="block1">1</div>
<div class="block3">3</div>
<div class="block2">2</div>
<div class="block6">4</div>
</div>
.wrapper {
column-count: 2;
column-width: 100px;
-moz-column-width: 100px;
-webkit-column-width: 100px;
width: 260px;
}
div {
border: 1px solid #999;
display: inline-block;
margin: 10px;
width: 100px;
}
.block1 { height: 100px; }
.block2 { height: 130px; }
.block3 { height: 150px; }
.block4 { height: 100px; }
This solution is not compatible with IE9 and below.
Block Height Known
If you do know your block heights you can solve this problem by using absolute positioning.
block1 {
height: 100px;
position: absolute;
left: 0;
top: 0;
}
block2 {
height: 110px;
position: absolute;
left: 0;
top: 100px; /* The height of the div above it */
}
A big drawback is dynamic content; we seldom know block height. So this solution is very limited in its application unless you are willing to calculate the height block height.
If you are willing to use JS
Use a plugin like Masonry. Both in vanilla js or jQuery flavour.
Other Options
This leaves you with the following options that require some compromises.
Group your blocks into columns. See this Fiddle for a demo. This will alter the flow of your blocks to vertical, then horizontal.
Use display: inline-block; vertical-align: top; on your blocks. This will leave some white space below your blocks.
Force the height of your blocks, rendering this a non-issue. For blocks with additional content use the overflow property to allow in-block scrolling.
As others have commented, you could attempt to calculate the height of the blocks on the server.
You could try a mix of flex and float (only tested in Firefox/IE10 and safari 5.1.7 , cause to my own opinion, CSS is not your solution)
http://codepen.io/gcyrillus/pen/zgAiw
But, in any CSS case you choose, the best is to relay on the mansonry script.
CSS is not really adapted to this kind of layout. At this time you have many CSS method for layout and basicly: display and float.
You can easily use this together within your html tree structure but this methods are not meant to be mixed. A boxe will be floatting, an inline-level-box or block-level-box and each are suppose to interact in the flow.
Float, breaks a line before itself after a non floatting element or slides down untill it has enough room, that you dispatch right/left via CSS r not.
inline-block moves away from floatting elements and breaks a line if not enough room left, floatting elements among inline-blocks will keep breaking a line before floating.
Column CSS will fill columns with content one by one. see : http://codepen.io/gcyrillus/pen/AtazJ
Inline-flex elements seems to work with floatting elements ... but is it suppose to untill it's a validated rule ?
What seems to be wised to me , is to used a javascript for the layout expected and relay on float or display:inline-block + width as a fall back.
Last solution is to think this ahead on your server side and dispatch your items in 2 containers with another appropriate markup if that is possible ( no idea of your real life content dispatched in your ol li ).
The CSS for the FLEX test :
li.gruppe
{
background: #048;
color: white;
font: bold 32px Arial, sans-serif;
text-align: center;
box-sizing:border-box;
border-bottom:1px solid white;
border-bottom:1px solid white;
display: -webkit-inline-flex;
display: -moz-inline-flex;
display: -ms-inline-flex;
display: inline-flex;
width:50%;
}
li:nth-child(even){
float:right;
clear:right;
border-left:1px solid white;
margin-top:0;
}
EDIT: This is an interesting solution, but unfortunately it does not solve the problem that was asked for.
The solution I propose here puts subsequent elements into alternating columns, so: 1 -> left, 2 -> right, 3 -> left, 4 -> right, etc.
This is a interesting problem by itself, but not what was asked for.
Thanks to #Nils in the comments for pointing this out.
Original answer
Here is my attempt with flex!
https://jsfiddle.net/vqLr8t3e/
I am not sure if it works in IE11.
Code
.the-beginning {
background: green;
color: white;
font-weight: bold;
text-align: center;
cursor: pointer;
}
.the-end {
background: red;
color: white;
font-weight: bold;
text-align: center;
cursor: pointer;
}
.container-outer {
overflow: hidden;
}
.container {
display: flex;
flex-wrap: wrap;
flex-direction: column;
max-height: 19999px;
margin-top: -10000px;
}
.container > div {
width: 50%;
box-sizing: border-box;
border: 5px solid grey;
padding: 5px;
background: white;
order: 1;
}
.container > div:nth-child(odd) {
order: -1;
}
.container > div:nth-child(1),
.container > div:nth-child(2) {
margin-top: 10000px;
}
<div class="the-beginning">THE BEGINNING</div>
<div class="container-outer">
<div class="container">
<div>LEFT 0</div>
<div>RIGHT 0<br>RIGHT 0</div>
<div>LEFT 1<br>LEFT 1<br>LEFT 1</div>
<div>RIGHT 1</div>
<div>LEFT 2</div>
<div>RIGHT 2<br>RIGHT 2<br>RIGHT 2</div>
</div>
</div>
<div class="the-end">THE END</div>
Idea
Use flex-direction: column; and flex-wrap: wrap; on the container, and width: 50%; on the items, as a first step towards showing the items in columns.
Use order: -1; and order: 1 to sort odd and even elements into different columns.
Use a gratuitous margin-top: 10000px; on the first element of each column, and a max-height: 19999px; on the container, so that no two such items fit into one column. This will make sure each of these items starts in a new column. Compensate with a negative margin-top on the container. Cut it off with an outer container with overflow: hidden;.
I'm not sure if I got this right . .
"the 2's should stand alone on the right side and the 1, 3's and 4
should stand on the left side (without space between them)."
html:
<div id="box">
<div class="data">1</div>
<div class="data" style="float:right">2<br/>2<br/>2<br/>2</div>
<div class="data">3<br/>3</div>
<div class="data">4</div>
</div>
css:
#box {
width:100%;
height:auto;
float:left;
}
.data {
height:auto;
width:50%;
float:left;
background-color:#ccc;
border-bottom:solid 1px #000;
}
Fid:
http://jsfiddle.net/YdEW9/26/
This is pure css. Everything is floated left then gave inline-css to float:right on the div with (4) 2's
I kinda don't know how to set the inline-css without javascript. Server side maybe? but I doubt you can get the height of the elements.
Well anyway hope this helps.
PURE CSS SOLUTION:
Add the following to your css file:
ol.context li:nth-child(even) {
float: right;
}
DO NOT change your html or anything else.
Result in FF:
--
How it Works
Instead of floating all your elements "left" and creating gaps, we float each container according to the side/column the element they reside in.
It's kinda hard for me to explain the problem, so let me give you the URL.
Visit http://www.ucaftercruz.com
If you look at the footer, theres an unordered list aligned vertically. When you drag the browser and make it smaller, the list goes from one line to two lines. How do I make it so that it stays in one line and in the center of the footer regardless of window size?
I suspect it has something to do with my divs.
Here is my html code:
<div style="clear:both;">
<div id="footer">
<div id="footer-pages">
<ul>
<li>About the blog</li><span></span>
<li>The Authors</li><span></span>
<li>Archives</li><span></span>
<li>Credits</li><span></span>
<li>FAQ</li>
</ul>
</div>
And here is my CSS:
#footer {
height: 100px;
background-color: #d0cabc;
font-size: 12px;
}
#footer a {
color: #606060;
}
#footer-pages {
padding: 20px 0;
border: 0px solid green;
margin: 0 auto;
width: 35%;
}
#footer li {
display: inline-block;
margin: 0 15px;
}
In order to make it so that the menu can be dynamically added to, you should make the container width (#footer-pages) to be a fairly wide div, and center the contents. I used the following code via the inspector:
#footer-pages {
width: 100%;
text-align: center;
min-width: 500px;
}
add #footer { white-space: nowrap } to your css for footer. You could also add min-width:###px where ### is big enough.
In the first case, you tell the rendering engine to avoid making the box any smaller than the minimum required to contain the text. I actually don't know for sure if this will work on this kind of list.
In the second case, which I know works, but is a little less elegant, will force the engine to keep the layout box no smaller than a specific amount -- if you choose an amount that will contain the text, it may add scrollbars (which you can control with the overflow property) but not cause the text to wrap.
So I've been trying to figure out an issue with my divs here; how to translate my design into the actual layout, and I've not had much luck with research or implementation. In the attached link, where you see //PORTFOLIO and then a line extending to the edge of the content area, there's a red line. Right now I have both the //PORTFOLIO and red line divs set to a specific pixel width, but I want to be able to have both divs auto-set their width (the first to automatically set its width based on how much the //TITLE takes up, and the second to fill the remaining space in the container) since I'll have other sections of the website doing the same thing, and don't want to measure specifically for each area. Any suggestions are most welcome, thank you so much!
Example
See: http://jsfiddle.net/GmtMK/1/ (change the width of the browser window)
<div id="columnA">
<div id="title">//Portfolio</div>
<div id="line"></div>
</div>
#columnA {
font-family: 'ProximaNovaRegular', Geneva, sans-serif;
font-size: 19px;
text-transform: uppercase;
color: #C10000;
margin-bottom: 20px;
letter-spacing: 4pt;
}
#title {
float: left
}
#line {
overflow: hidden;
height: 9px;
border-bottom: 1px solid #c10000;
}
First, let me complement you on your website, it looks nice and stylish!
Secondly, I have a solution for you, using display: table css property, however, it requires adding an <hr /> element is it won't let you have cells of uneven height:
<div id="columnA">
<div id="title">//Portfolio</div>
<div id="line"><hr /></div>
</div>
#columnA {
width: 400px;
display:table;
}
#title {
display:table-cell;
width: 175px;
}
#line {
display:table-cell;
width: auto;
}
hr {
background-color: #C10000;
height: 1px;
border: 0;
}
Please see full example: http://jsfiddle.net/GmtMK/