1

I want to change the order of the div on specific width (max-width : 640px). In my JSFiddle example I want the yellow box from the 2nd section to be under the text when the window width is smaller than 640px.

I want the 2nd section to act like first one at that width. Instead of the yellow boxes I will be using images so every time at that width images should be under the text, no matter how they are placed in html.

Here is the JSFiddle example.

    <!-- Cell 1 -->
    <div class="tableCell">
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ac facilisis ante. Aenean et augue feugiat, gravida ligula quis, pharetra quam. Integer nec sodales erat. Mauris fringilla eleifend condimentum. Cras eleifend sodales nisi in tempor.</p>
    </div>

    <!-- Cell 2 -->
    <div class="tableCell">
        <div id="box"></div>
    </div>
Hashem Qolami
  • 97,268
  • 26
  • 150
  • 164
Hann
  • 69
  • 2
  • 8
  • 1
    Using CSS tables, I'm afraid that it won't happen. Assuming two options to position the elements `margin` and `position: relative`, neither works on table cell elements. – Hashem Qolami Aug 16 '14 at 11:42
  • yes @HashemQolami is right, why do you use table cell, If you want you can achieve it with `float` – Ganesh Gaxy Aug 16 '14 at 11:44
  • @GaneshGaxy Because I want to keep "vertical-align:middle" between cells. – Hann Aug 16 '14 at 11:46
  • @Hann Then you could follow **[this approach](http://stackoverflow.com/questions/18516317/vertically-align-an-image-inside-a-div-with-responsive-height/18516474#18516474)** for vertical alignment without using CSS tables. – Hashem Qolami Aug 16 '14 at 11:47
  • i checked your jsfiddle, wait i work on it, but explain briefly what you wanna do? – Ganesh Gaxy Aug 16 '14 at 11:47
  • @HashemQolami Then what would be the solution if I will use that approach ? – Hann Aug 16 '14 at 11:49
  • @Hann Let me update the fiddle please. – Hashem Qolami Aug 16 '14 at 11:50
  • @GaneshGaxy Think that the cell which is have boxes will have images, for example a Phone image, so when the user it is on a mobile screen or tablet I want to display the text first instead of the image/phone first. So basically every cell containing a image to be displayed last. – Hann Aug 16 '14 at 11:51

4 Answers4

3

Why CSS tables won't help in this case

Assuming two options to position the elements margin and position: relative, neither works on table cell elements. (margin is not applicable to table cells and also the effect of relative positioning is undefined for them).

8.3 Margin properties 'margin'

Applies to: all elements except elements with table display types other than table-caption, table and inline-table

9.3.1 Choosing a positioning scheme: 'position' property

The effect of position:relative on table-row-group, table-header-group, table-footer-group, table-row, table-column-group, table-column, table-cell, and table-caption elements is undefined.

Therefore you probably need to use another layout scheme.

Choosing a layout method

There are two other options to create the columns, CSS floats and inline-blocks (Actually there are three. The third one, CSS Flexible box layout is only supported in modern web browsers at the time of writing; Hence I ignored that).

Since the contents should be aligned vertically at the middle, I'd go with using inline-block columns.

Important Note: You should remove the white-space between inline-block elements (the columns in this case) in order to prevent the layout from being broken (by two 50% columns).

Column ordering

In order to push and/or pull columns to a side, you could either use a positive/negative margin value or use relative positioning and specify left/right properties.

For instance, by using margin you'll have:

EXAMPLE HERE

.col {
    width: 50%;

    display: inline-block;
    padding: 0 10px;
    vertical-align: middle;
    
    -webkit-box-sizing: border-box; /* to calculate width of the box including */
    -moz-box-sizing: border-box;    /* borders and padding (10px left/right)   */
    box-sizing: border-box;
}

.col.push-right { margin-left: 50%; }
.col.push-left { margin-left: -100%; }

@media only screen and (max-width : 640px) {
    .col {
        display: block;
        width: auto;
        text-align: center;
        padding: 10px;
    }
    
    .col.push-right, .col.push-left {
        margin-left: auto;
    }
}

Or by using relative positioning you'll end up with:

EXAMPLE HERE

.col {
    /* other declarations as above... */
    width: 50%;
    position: relative;
}

.col.push-right { left: 50%; }
.col.push-left { right: 50%; }

@media only screen and (max-width : 640px) {
    .col {
        /* other declarations... */
        display: block;
        width: auto;
    }

    .col.push-right { left: auto; }
    .col.push-left  { right: auto; }
}

Regardless of inline-block columns, this approach is widely used by most CSS frameworks such as Twitter Bootstrap and Zurb Foundation.

Additionally in both of the above approaches, your HTML markup should be changed like so:

<div class="container">
    <div class="col push-right">
        <p>Lorem ipsum....</p>
    </div><!--  comment out spaces/new lines/tabs between
                these two inline-block columns in order to remove the gap.
     --><div class="col push-left">
        <div id="box"></div>
    </div>
</div>
Community
  • 1
  • 1
Hashem Qolami
  • 97,268
  • 26
  • 150
  • 164
2

There is only one real way to change order in CSS that I know of (any other way is kind of a hack). You need to use flexbox.

The problem is that there is no way to distinguish between your parent elements whether it contains a box or not. I suggest adding extra classes.

That being said, this is how you can change the order of the second row:

.tableRow {
  display: flex;
  flex-direction: column-reverse;
}

or use the order properties

.tableRow {
  display: flex;
  flex-direction: column;
}
.tableCell {
  order: 2;
}
.tableCell:first-child {
  order: 1;
}

CSS-Tricks has a good flexbox reference.

cuth
  • 514
  • 6
  • 8
  • 1
    The only issue with flexbox is that it's not supported very well throughout Internet Explorer. OP might have plans to support older browsers for backwards-compatibility. Other than that, I'd recommend to use flexbox as well. – Ivan Aug 16 '14 at 14:39
  • @ivan that's true. But we are changing the order on a "mobile" size. Flexbox has good support on mobile devices since not many phones are running IE9. New versions of IE have Flexbox behind a vendor prefix. – cuth Aug 16 '14 at 15:12
  • Yes, but @media queries also can work on desktops. I think he means a responsive webpage, period. – Ivan Aug 16 '14 at 15:25
1

You might want to play with :before and :after: jsfiddle.net/ra64oyk2

  • On normal screen you'll use :before (left) and :after (right).

  • On reduced screen you'll use :after.

Now you can delete the div containing the boxes.

To preserve your original layout, you'll need to alter the children of the .tableCell elements so they get a display: table-cell. Then, you may want to change some class names.

In order to know where to put the images on standard screen size, add some class names to the div.tableCell containg the text:

  • imgRight for the 1st row

  • imgLeft for the 2nd row.

Then you can add this to your CSS:

.tableCell.imgRight:after {
    content: ' ';
    width: 200px;
    height: 200px;
    background: yellow;
    display: table-cell;
}

.tableCell.imgLeft:before {
    content: ' ';
    width: 200px;
    height: 200px;
    background: yellow;
    display: table-cell;
}

.tableCell > * {
    display: table-cell;
    vertical-align: middle;
}


@media only screen and (max-width : 640px) {
    .tableCell > * {
        display: block !important;
    }
    .tableCell:after {
        content: ' ';
        width: 200px;
        height: 200px;
        background: yellow;
        display: block !important;
        margin: 0 auto;
    }
    .tableCell:before {
        display: none !important;
    }
}
Thomas
  • 212
  • 1
  • 8
  • Can you show this in a JSFiddle example using images ? I couldn't make it work. Thanks. – Hann Aug 16 '14 at 13:01
  • @Thomas You're fiddle demo looks correct, but you've used `:after`/`:before` pseudo elements to create the yellow boxes which should be replaced by valid images in action. Since `content: url(...)` doesn't have a good browser compatibility, you'll end up with duplicating the image, before and after the paragraph. – Hashem Qolami Aug 16 '14 at 13:22
  • Are you sure about that? It looks fine in here: http://www.w3schools.com/cssref/tryit.asp?filename=trycss_content_url. I know I shouldn't believe everything I read but they also say that it's even supported by IE8 oO – Thomas Aug 16 '14 at 13:28
  • Also, I checked, you can leave `content: ' ';` and use `background: url(...);` or `background-image: url(...);`. – Thomas Aug 16 '14 at 13:43
  • @Thomas You're right, `content: url(...)` on pseudo-elements is valid and supported in IE8+ I got it confused with [using `content: url(...)` on an image](http://stackoverflow.com/questions/2182716/how-can-we-specify-src-attribute-of-img-tag-in-css). Anyways, this will work in this particular case and that's fair enough :) – Hashem Qolami Aug 16 '14 at 13:47
  • 1
    @Thomas Your solution is very good, but if we have for example 20 rows like 1st imgLeft, 2nd imgRight, 3rd imgLeft, 4th imgRight and so on, how you set different images for every row ? I think it would needs to create a lot of classes. I think the Hashem's solutions is more flexibile, I can add images through HTML and I am not conditioned by CSS :before. – Hann Aug 16 '14 at 13:49
  • You'll need to set the different images anyways. You dont have to create more classes since you have row IDs. The image just won't be directly in HTML and there won't be any `alt`. So yeah Hashem's solution might be better. – Thomas Aug 16 '14 at 14:06
1

To change the actual order of the HTML, the best (and least hackiest) way to do this will be with Javascript.

As you have the jQuery tag in your question, I'll assume that you'll be okay with using jQuery for changing the div order:

<!-- (best if you label those columns per-row e.g. firstColumn, secondColumn) -->
<div class="tableCell firstColumn">
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ac facilisis ante. Aenean et augue feugiat, gravida ligula quis, pharetra quam. Integer nec sodales erat. Mauris fringilla eleifend condimentum. Cras eleifend sodales nisi in tempor.</p>
</div>

<div class="tableCell secondColumn"> 
    <div id="box"></div>
</div>

And then for your Javascript:

window.onresize = function(){
    if ($('body').width() < 640){
        //if body width is less than 640px, then put the second column before the first column
        $('.tableCell.firstColumn').insertAfter(".tableCell.secondColumn");
    }
    else{
        //if body width is more than or equal to 640px, then reset the ordering.
        $('.tableCell.secondColumn').insertAfter(".tableCell.firstColumn");
    }
}

You can further optimize the Javascript I wrote, but you get the idea.

Here's the demo that is applied to the first row: jsFiddle

Also, Cuth here also provided a very good answer: to use flexbox. If you're not worried about flexbox not being supported in some versions of IE and completely absent in Opera Mini, then I would strongly suggest you to use that answer instead.

Ivan
  • 307
  • 1
  • 16
  • I think this is the easiest method yet, but using your example when resizing the window the column goes in the right place (last) but if we keep same width (<640) and we are refreshing the page no more works that's because `window.onresize` I think. – Hann Aug 16 '14 at 14:21
  • Yes, I simply gave you the concept. You can put the anonymous function into a function that can be resuable, so you can implement it into window.onload and/or window.onresize. [Here's how I do it](http://wffs.sq10.net/lib/wffs.js), focus on the determineContentOrder function. – Ivan Aug 16 '14 at 14:23
  • That, and depending on how your webpage is set up, you can even have the content order function run at the very bottom of the HTML, so you don't have to wait for the images/css to load and etc. – Ivan Aug 16 '14 at 14:33
  • I would accept this as main answer because this one was the easiest and the best in my context. Also I've tested all answers and all of them works very well. – Hann Aug 16 '14 at 14:57