table-cell - some kind of colspan? - css

I am a bit puzzled right now, because I had CSS code that worked, but it wasn't beautiful at all. I now want to rework this CSS styles and build them via LESS. And I have big problems with display:table; / display:table-row; and display:table-cell;.
For example I have the following code: http://jsfiddle.net/La3kd/2/
How can I do it that the last cell (center) does not shift the above second cell to the right? The last cell should have the width of the 2 cells above. Some kind of colspan is needed. It is so weird, because I have the impression that it worked before I reworked the code. But now all elements to the right are totally shifted.

CSS has no colspan analog. Based on your example, you can just mark up your last row as a separate nontably block.
You could also use display: table-caption in conjunction with caption-side: bottom to display the table row as a last “row” that spans all columns. See live demo.

One idea would be to leverage absolute positioning. Relative position a wrapper around the table, then all absolute positioning becomes coordinate centric to the wrapper. See below. Notice I define a class of tableWrapper which will be set position:relative, then define class of tableRow and - I'm assuming you'll set .tableRow div { display: table-cell; } so I didn't bother putting a class on each div. You'll have to find a way to prevent it from overlapping the div below it if it's height gets larger than the 2nd div. Should be very doable.
<div class="tableWrapper">
<div class="tableRow">
<div>Column 1</div>
<div>Column 2</div>
</div>
<div class="tableRow">
<div style="border: 1px solid black; position: absolute; width: 100%;">appears like colspan=2</div>
<div> (only here to force a row break before the next table row)</div>
</div>
<div class="tableRow">
<div>Column 1</div>
<div>Column 2</div>
</div>
</div>

Use a real table when you are forced to do so to get the layout you want.
The ONLY necessary reason to not use a table for layout is that a speaking browser for the blind gives the row number and column number coordinates of each table cell. This confuses the blind reader when table cells are used for layout.
Of course, it is much easier to use margins, borders, and padding where they do the job much better than faking them with tables, but when you have something with a layout similar to a newspaper want-ad page, it is better to use a real table, a set of nested tables, or a table full of divs.
I will always use div or div faking a table with display table parts when they work.
When they do not work, or when the div layout falls apart at different screen resolutions, I will use a real table. It never falls apart.
This kludgery by the W3C would have had a better solution with a CSS code to tell the speaking browser to not treat a real table as a table.
I also treat a table of comments arranged around the page title as tabular data, even though it is not numeric. Tabular data can include categorical data.
One idea is to hide (with same foreground and background colors) a disclaimer telling the blind person to ignore the table coordinates the speaking browser provides because the use of a table was forced by the lack of ability to make the layout work with divs.

Depending on your needs, flexbox layout may accomplish what you are looking for.
div.table{
display:block;
width:100%;
}
div.table >div{
display:flex;
width:100%;
border:1px solid gray;
flex-direction:horizonal;
}
div.table > div >div{
display: block;
flex-grow:1;
border-bottom:1px solid #ddd;
vertical-align: middle;
height:30px;
padding:4px;
}
See demo:
http://jsbin.com/mimegodiba/edit?html,css,output

When I needed colspan I used "display: grid" instead, and defined the columns using grid-template-areas.
There's a brilliant example here: https://css-tricks.com/snippets/css/complete-guide-grid/ (look for grid-template-areas)

The table-caption is a good idea if you need header and footer row regardless of columns width...
The absolute positioning works great except when your text is line-feeding at least once more than other cells in that row...
So here's a pseudo solution to have header in between rows of a responsive table and be sure to have line-feed according to the table header content (which is important if the table is populated dynamically). I've also included a sort of colspan as well (although not line-feeding accurately) :
CSS :
.table
{ display:table;
position:relative;
}
.table > .header
{ display:table-caption;
position:absolute;
left:0;
right:0;
}
.table > .l50{right:50%;}
.table > .r50{left:50%;}
.table > .row{display:table-row;}
.table > .row > *{display:table-cell;}
/* We add an extra cell where neededed to allow or header repositioning using % instead of fixed units */
.table > .header + .row > :last-child
{ width:1%;
max-width:1px;
overflow:hidden;
visibility:hidden;
}
.table > .header + .row > :last-child > div
{ float:left;
display:inline;
visibility:hidden;
width:10000%;/* 100% = parent element width (1%) ⇒ 100*100% = gran-parent element width*/
}
.table > .header + .row > :last-child > div > .l50
.table > .header + .row > :last-child > div > .r50{width:5000%;}
/* No responsive line-feed thought it's possible using % to estimate the size the span should take but it's not accurate (see HTML render) */
.table > .row > div > .span{position:absolute;left:0;right:33%;}
/* THIS MAKES SURE TRADITIONAL CELLS ARE VISIBLE */
.table > .row > .top
{ position:relative;
z-index:1;
}
http://jsfiddle.net/sp2U4/

I found a solution using jquery and table-layout: fixed. Here is my fiddle: http://jsfiddle.net/emilianolch/5nvxv5ko/
HTML:
<div class="table">
<div class="table-row">
<div class="table-cell">
top left cell
</div>
<div class="table-cell">
top right cell
</div>
</div>
<div class="table-row">
<div class="table-cell colspan">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</div>
</div>
<div class="table-row">
<div class="table-cell">
bottom left cell
</div>
<div class="table-cell">
bottom right cell
</div>
</div>
</div>
CSS:
.table {
display: table;
table-layout: fixed;
width: 100%;
border-collapse: collapse;
}
.table-row {
display: table-row;
border-collapse: collapse;
}
.table-cell {
display: table-cell;
padding: 5px;
border: 1px solid black;
}
.table-cell.colspan {
display: none;
/* collapse border */
margin-top: -1px;
margin-bottom: -1px;
}
JS:
var rowWidth = $('.table-row:first').width();
var colWidth = $('.table-cell:first').width();
var marginRight = colWidth - rowWidth + 11;
$('.table-cell.colspan').css('margin-right', marginRight + 'px').show()

I could achieve the col-span with the table-row-group
div {
border: solid 1px;
min-width: 10px;
min-height: 10px;
}
.table-head {
display: table-row;
}
.table-row {
display: table-row;
}
.table-cell {
display: table-cell;
}
.table-row-group {
display: table-row-group;
}
.table-cell-group {
display: table-row;
}
<div style="display: table;">
<div class="table-head">
<div class="table-cell">h1</div>
<div class="table-cell">h2</div>
</div>
<div class="table-row">
<div class="table-cell">c1</div>
<div class="table-cell">c2</div>
</div>
<div class="table-row-group">
<div class="table-cell-group">
cc
</div>
</div>
<div class="table-row">
<div class="table-cell">c1</div>
<div class="table-cell">c2</div>
</div>
<div class="table-row">
<div class="table-cell">c1</div>
<div class="table-cell"></div>
</div>
</div>

CSS3 has a column-span attribute. But please try to use flexbox or css grid for layout.

Related

Bootstrap 3: How do you align column content to bottom of row

I have a row in Bootstrap 3 and 3 columns in that row. I want to align two of the columns to the bottom of the row and keep the first column at the top. When I use the traditional approach with position relative in the parent and absolute for both columns I get a weird behavior which I imagine is because of something in twitter bootstrap. Here's a bootply of what's happening:
http://www.bootply.com/125735
The absolute forces all the columns on top of eachother, can anyone help me out? The end result is to have something like so:
http://fahadalee.wordpress.com/2013/12/31/bootstrap-3-help-how-to-alin-div-in-bottom/
Thanks
You can use display: table-cell and vertical-align: bottom, on the 2 columns that you want to be aligned bottom, like so:
.bottom-column
{
float: none;
display: table-cell;
vertical-align: bottom;
}
Working example here.
Also, this might be a possible duplicate question.
Vertical align bottom and remove the float seems to work. I then had a margin issue, but the -2px keeps them from getting pushed down (and they still don't overlap)
.profile-header > div {
display: inline-block;
vertical-align: bottom;
float: none;
margin: -2px;
}
.profile-header {
margin-bottom:20px;
border:2px solid green;
display: table-cell;
}
.profile-pic {
height:300px;
border:2px solid red;
}
.profile-about {
border:2px solid blue;
}
.profile-about2 {
border:2px solid pink;
}
Example here: http://www.bootply.com/125740#
When working with bootsrap usually face three main problems:
How to place the content of the column to the bottom?
How to create a multi-row gallery of columns of equal height in one .row?
How to center columns horizontally if their total width is less than 12 and the remaining width is odd?
To solve first two problems download this small plugin https://github.com/codekipple/conformity
The third problem is solved here http://www.minimit.com/articles/solutions-tutorials/bootstrap-3-responsive-centered-columns
Common code
<style>
[class*=col-] {position: relative}
.row-conformity .to-bottom {position:absolute; bottom:0; left:0; right:0}
.row-centered {text-align:center}
.row-centered [class*=col-] {display:inline-block; float:none; text-align:left; margin-right:-4px; vertical-align:top}
</style>
<script src="assets/conformity/conformity.js"></script>
<script>
$(document).ready(function () {
$('.row-conformity > [class*=col-]').conformity();
$(window).on('resize', function() {
$('.row-conformity > [class*=col-]').conformity();
});
});
</script>
1. Aligning content of the column to the bottom
<div class="row row-conformity">
<div class="col-sm-3">
I<br>create<br>highest<br>column
</div>
<div class="col-sm-3">
<div class="to-bottom">
I am on the bottom
</div>
</div>
</div>
2. Gallery of columns of equal height
<div class="row row-conformity">
<div class="col-sm-4">We all have equal height</div>
<div class="col-sm-4">...</div>
<div class="col-sm-4">...</div>
<div class="col-sm-4">...</div>
<div class="col-sm-4">...</div>
<div class="col-sm-4">...</div>
</div>
3. Horizontal alignment of columns to the center (less than 12 col units)
<div class="row row-centered">
<div class="col-sm-3">...</div>
<div class="col-sm-4">...</div>
</div>
All classes can work together
<div class="row row-conformity row-centered">
...
</div>
I don't know why but for me the solution proposed by Marius Stanescu is breaking the specificity of col (a col-md-3 followed by a col-md-4 will take all of the twelve row)
I found another working solution :
.bottom-column
{
display: inline-block;
vertical-align: middle;
float: none;
}

Showing ellipsis in CSS table-cell element

I have a 100% width table containing several cells. I want one of this cells to always show its contents in one line white-space: nowrap and to display an ellipsis at the end of the line if the contents exceed the table cell text-overflow: ellipsis.
The problem i have is that the table will stop contracting it's with when reaching the cells content. So the minium width of the cell will allways be the width of its content instead the table will be pushed out as a whole.
I just can't figure out how to solve this:
My HTML:
<div class="otrCompactView">
<div class="otrLastEditTable">
<div class="otrLastEditRow">
<div class="otrLastEditor">LastEditor</div>
<div class="otrLastEdited">LastModified</div>
</div>
</div>
<div class="otrTitleRow otrRow">
<div class="otrTitle">Title asdasdasdas asd asd asd asdas as asd </div>
</div>
<div vlass="otrTaskRow otrRow">
</div>
<div class="otrColumnsRow otrRow">
<div class="otrColumns"></div>
</div>
</div>
My CSS:
.otrCompactView {
display: table;
background: yellow;
width: 100%;
height: 100%;
}
.otrRow {
display: table-row;
}
.otrLastEditTable {
display: table;
width: 100%;
}
.otrLastEditRow {
display: table-row;
}
.otrLastEditor {
display: table-cell;
}
.otrLastEdited {
display: table-cell;
text-align: right;
}
.otrTitle {
border: 1px dotted red;
min-width: 50px;
white-space: nowrap;
}
And a fiddle for direct testing:
http://jsfiddle.net/67B6G/
Does this look like what you're after?
updated
HTML
<div class='table'>
<div class='row'>
<div class='cell'>Something quite long</div>
</div>
<div class='row'>
<div class='cell'>
here is some moreSomething quite long that should exceed the table cell.Something quite long that should exceed the table cell.
</div>
</div>
</div>
CSS
.table{
margin:0;
padding:0;
display:table;
table-layout: fixed;
width:100%;
max-width:100%;
}
.row{
display:table-row;
}
.cell{
display:table-cell;
border:1px solid grey;
}
.cell:last-child{
white-space: nowrap;
overflow:hidden;
text-overflow: ellipsis;
}
Here's a way to do it without using table-layout: fixed that allows you to keep dynamic widths with jQuery.
HTML:
<div class="table">
<div class="left">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</div>
<div class="right">Lorem Ipsum</div>
</div>
In the CSS, you use your standard ellipsis code but add max-width: 0 (as explained here with respect to actual table elements):
.table {
display: table;
width: 100%;
}
.left, .right {
display: table-cell;
padding: 0 5px 0 5px;
max-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
If you stopped there, you'd end up with each child div taking up 50% of the total width of the parent div, so you still wouldn't have fit-to-content dynamic widths. To remedy this, I adapted this code, which calculates the width of the text in an element, to calculate the width and then use that to dynamically set the width of the right column. The left column will then have the ellipsis.
// Calculate width of text from DOM element or string. By Phil Freo <http://philfreo.com>
$.fn.textWidth = function(text, font) {
if (!$.fn.textWidth.fakeEl) $.fn.textWidth.fakeEl = $('<span>').hide().appendTo(document.body);
$.fn.textWidth.fakeEl.text(text || this.val() || this.text()).css('font', font || this.css('font'));
return $.fn.textWidth.fakeEl.width();
};
$('.right').on('input', function() {
var $width = $(this).textWidth(); // Get width of text
$width += 10; // Add left and right padding
$(this).width($width); // Set width
}).trigger('input');
Note that the above code requires you to take padding into account; otherwise, the right column will have an ellipsis as well. Here's a fiddle.
To use this in a table with multiple rows, you could modify the jQuery iterate over the cells in a column and set the width of the column to the requisite width of the widest cell in the column. Or, if you know which one is the widest, you can just direct the jQuery to get the width of that.

using overflow in css

How can i set the width of the first 2 divs to be dynamic (fit the contents width), while the 3rd div should use remaining horizontal space and be horizontally scrollable.
The result i need is that all 3 divs sit side by side and the 3rd div is hoziontally scrollable.
Script i have is as follows
HTML
<div id="a">
<table>
<tr><td>text</td></tr>
</table>
</div>
<div id="b">
<table>
<tr><td>text</td></tr>
</table>
</div>
<div id="c">
<table>
<tr><td>text</td></tr>
</table>
</div>
CSS
div#a
{
float: left;
}
div#b
{
float: left;
}
div#c
{
float: left;
width: 100%;
overflow-x: scroll;
}
The above script pushes div3 to the next line, which i dont want.
If you float #a and #b to the left, #c will fill the rest of the parent's width.
To get #c horizontally scrollable, you style its content container as:
#c .scroll-content {
/* You shouldn't do this on a table, but rather on a wrapping container. */
display: inline-block;
white-space: nowrap;
overflow: auto;
overflow-y: hidden;
}
I made an example at JSFiddle.
You should set a parent div to hold them all together in the same row. Something like this instead should work.
<div id="parent">
<div id="a">
<table>
<tr><td>text</td></tr>
</table>
</div>
<div id="b">
<table>
<tr><td>text</td></tr>
</table>
</div>
<div id="c">
<table>
<tr><td>text</td></tr>
</table>
</div>
</div>
div#a
{
float: left;
}
div#b
{
float: left;
}
div#c
{
float: left;
}
#parent{
width: 100%;
overflow-x: scroll;
}
Also you might want to refactor your code. Since all of the divs are floating left, you might want to use just one class that floats to the left. I hope this helps.
The CSS...
#a {
float:left;
border:solid 1px #000;
width:33%;
}
#b {
float:left;
border:solid 1px #000;
width:33%;
}
#c {
float:left;
border:solid 1px #000;
width:33%;
}
.scroll{
float:left;
overflow:auto;
width:100%;
}
.content {
width:1000px;
overflow:auto;
}
And the HTML...
<div id="a">
This is text within my first content box
</div>
<div id="b">
This is text within my second content box
</div>
<div id="c">
<div class="scroll-content">
This is text within my third content box and this is horizontal and scrollable
</div>
</div>
UPDATED JSFIDDLE LINK BELOW AGAIN!!!
And a demo on jsfiddle - http://jsfiddle.net/GeLqV/1/
Mark, this will work for you now. I now see that you wanted all three divs on the same row, and the last one being able to horizontally scroll. Look at my jsfiddle demo. No matter what your screen size will be, all three div's are fluid in size and will stay together (for the most part).

Two column dynamic layout

I have several boxes containing the following!
<div class="box">
<div class="image">
<img src="anything.png" /> <!-- The width is dynamic -->
</div>
<div class="box-text">
<h2>Some Title</h2>
<p>Lorem ipsum ...</p>
</div>
</div>
The problem is that the text floats to the left after the image. I want it to go straight down, as I've marked it in the following image:
This is the way it should look like:
I do not want to use tables or javascript. I can't use margin-left for the box-text, because the width of the image is dynamic.
Thanks for your contribution!
try using display: table for your box class and display: table-row for both image and box-text classes. Then align content using vertical-align: top on image and text.
Do not use tables, but make the <div>s act like the cells of a table, then make the inline content vertically aligned to the top:
​.box{display:table}
.image{display:table-cell;vertical-align:top;}
.box-text{display:table-cell;vertical-align:top;}
Check it here
Try this css:
.image { float: left; }
.box-text { float: left; }
Also you may want to stop floating elements after box div, so don't forget some clean up in the end:
<div style="clear:both"></div>
Here's an fiddle which shows how to acheive this layout: http://jsfiddle.net/X7j4P/
.box {
overflow:hidden;
}
.image {
float:left;
}
.image img {
width:300px;
}
.box-text {
width:300px;
float:left;
}
p {
margin-bottom:10px;
}

Make div of text only able to be as wide as its container

HTML
<div class="cont">
<div class="size" id="size1"></div>
<div class="text">Here is some textHere is some text Here is some text</div>
</div>
<div class="cont">
<div class="size" id="size2"></div>
<div class="text">Here is some textHere is some text Here is some text</div>
</div>​
CSS
.size {
background-color: red;
height: 100px;
width: 100px;
}
#size2 {
width: 200px;
}
.cont {
padding: 10px;
float: left;
}​
I need div.cont's widths to be the width of their contained div.size (in my actual example div.size is an image and its with will vary in each instance).
This isnt happening as div.text takes up more space than its container, how can I stop this and make the text wrap?
JS Fiddle
Deleted all the previous stuff as I have (after doing some digging) found an exact duplicate with working solution.
My answer was also incorrect (as the op then specified the image MUST be allowed to be variable)
The answer is found on this jsfiddle and is an exact duplicate of css - shrink a parent div to fit one child's width and constrain the width of the other child
//html
<div id="container">
<div id="child1"><img src="//www.google.com/logos/2012/Teachers_Day_Alt-2012-hp.jpg" width="300" height="116"></div>
<div id="child2">Lorem ipsum dolor sit amet.</div>
</div>
<br/>
<a id="longtext" href="#">lengthen/shorten text</a>
//css
#container{border:1px solid #f00;display:inline-block;margin:10px; display: table;}
#child1{border:1px solid #0f0;margin:10px; display: table-row; width: 1px;}
#child2{border:1px solid #00f;margin:10px; display: table-cell; width: 1px;}
img {border:1px solid #000;}
and basically it works using display:table-* (have a good read up)
'.size{ float:left;}'
let me know if this helps.
Expanding on Paul Sullivan's approach,
in your css:
.size {
...
display:block; /*assuming its an image - making sure its block level*/
...
}
.cont {
...
position:relative; /*add this to parent container if comming from cms*/
...
}
.text {
...
position:absolute;
top:100%; /*just to make sure content doesnt overlaps image*/
...
}
Just gives a plus point for getting content to stretch as wide as the image (plus padding)
Hope it helps,
Fiddle: http://jsfiddle.net/BKRsT/3/

Resources