table with specific responsiveness

Would be possible to create something that looks like a table (i.e. it does not need to be a <table></table>), but transforms as described below when the screen width shrinks?

wide screen (regular table):

 -------------------------
| **th1** | td1.1 | td1.2 |
| **th2** | td2.1 | td2.2 |
 -------------------------

medium screen (column for header and column for rest):

 -----------------
| **th1** | td1.1 | 
|         | td1.2 |
| **th2** | td2.1 | 
|         | td2.2 |
 -----------------

smallest screen (just put everything in one column):

 ---------
| **th1** | 
|  td1.1  | 
|  td1.2  |
| **th2** |
|  td2.1  | 
|  td2.2  |
 ---------

I have been looking around to find something like this, but it does not seem to exist. I also considered putting the data in a <dl></dl> and searched a lot about that as well, but I don't seem to find anything like this. I've seen loads of solutions for definition lists with a single definition and a hard-coded-width table layout for a definition list with multiple definitions, but that does not really meet my expectations.

My question is thus: is it possible to do something like this or am I being too demanding for web technologies?

The closest I got thus far was something like this:

dt {
  float: left;
  clear: left;
  width: 200px;
  margin: 0;
  padding: 10px;
  font-weight: bold;
}

dd {
  float: left;
  width: 200px;
  margin: 0;
  padding: 10px;
}

/* missing feature: when made less wide, the tdX.2 is under thX and not under tdX.1 */
<dl>
   <dt>th1</dt>
   <dd>td1.1</dd>
   <dd>td1.2</dd>
   <dt>th2</dt>
   <dd>td2.1</dd>
   <dd>td2.2</dd>
 </dl>

Upvotes: 1

Views: 248

Answers (5)

Although the answer of Pangloss was very helpful, I wanted to share with you my final solution, as I found it semantically cleaner than the multiple definition lists proposed. The thing that is missing is of course is something like a <di> tag to create nice definition lists. By using tables, something similar can be done as stated in the answer of Pangloss, but keeping all data together:

th {
  display: inline-block;
  min-width: 400px;
  text-align: left;
  vertical-align: top;
}

td {
  display: inline-block;
}

span {
  display: block;
  min-width: 400px;
}

@media (min-width: 800px) {
  span {
    display: inline-block;
  }
}
<table>
  <tr>
    <th>th1</th>
    <td>
      <span>td1.1</span>
      <span>td1.2</span>
    </td>
  </tr>
  <tr>
    <th>th2</th>
    <td>
      <span>td2.1</span>
      <span>td2.2</span>
    </td>
  </tr>
</table>

NOTE: the large min-width is to be able to see all possible states in my screen...

Upvotes: 0

Bruno Kos
Bruno Kos

Reputation: 645

Since you mentioned it, I would definitely use div elements instead of tables, as tables are much harder to manage, especially in responsive layouts. I would also like to use some jQuery here, but nothing serious.

HTML

<div id="sections">
  <section class="row-1">
    <p> **th1** </p>
    <p> **th2**</p>
  </section>

  <section class="row-2">
    <p class="row2-first">td1.1</p>

    <p class="row2-second">td2.1 </p>
  </section>

  <section class="row-3">
    <p class="row3-first">td1.2 </p>

    <p class="row3-second">td2.2 </p>
  </section>
</div>

CSS:

.row-1 {
  width: 33.3333%;
  float: left;
}

.row-2 {
  width: 33.3333%;
  float: left;
}

.row-3 {
  width: 33.3333%;
  float: left;
}

@media all and (max-width: 799px) {
  .row-1,
  .row-2,
  .row-3 {
    width: 50%;
    float: left;
  }
}

@media all and (max-width: 499px) {
  .row-1,
  .row-2,
  .row-3 {
    width: 100%;
    float: none;
  }
}

jQuery:

jQuery(document).ready(function($){

if ($(window).width() < 800 && $(window).width() > 500) {
   $(".row3-first").insertAfter(".row2-first");
   $(".row3-second").insertAfter(".row2-second");
}
else {
   //do nothing
}
});

jQuery(document).ready(function($){

if ($(window).width() < 500) {
   $(".row2-first").insertAfter(".row1-first");
}
else {
   //do nothing
}
});

My current example does not do exactly what you want, because I would need to create several more CSS classes for the example to completely rearrange elements as per your image, but I think you can get an idea on how to finish it. All you need to do is to add several CSS classes and create (copy-paste actually) the insertAfter function. So it is now all about combining.

You can check the working example on Codepen.

Upvotes: 0

Stickers
Stickers

Reputation: 78686

You could use media queries if you can adjust the markup similarly like below:

dt, dd {
  display: inline-block;
  vertical-align: top;
  margin: 0;
}
@media (max-width: 480px) {
  span {
    display: block;
  }
}
@media (max-width: 320px) {
  dt, dd, span {
    display: block;
  }
}
<dl>
  <dt>th1</dt>
  <dd>
    <span>td1.1</span>
    <span>td1.2</span>
  </dd>
</dl>
<dl>
  <dt>th2</dt>
  <dd>
    <span>td2.1</span>
    <span>td2.2</span>
  </dd>
</dl>

jsFiddle example, resize the frame and see.

Upvotes: 2

Saeed Salam
Saeed Salam

Reputation: 467

hows this - https://jsfiddle.net/4e8v5vrf/6/

HTML

<div class="col-wrapper">
    <div class="th-block">
    first title
    </div>
<div class="td-wrap">
        <div class="td-item">
          td 1.1
        </div>
        <div class="td-item">
          td 1.2
        </div>
</div>
</div> <!-- first row close -->

<div class="col-wrapper">
    <div class="th-block">
    second title
    </div>
<div class="td-wrap">
        <div class="td-item">
          td 2.1
        </div>
        <div class="td-item">
          td 2.2
        </div>
</div>
</div> <!-- second row close -->

CSS

@media (min-width:991px) {
.td-item {
  display:inline-table;
}
}

@media (min-width:768px) {
  .th-block, .td-wrap {
    display:inline-table;.
    vertical-align:top;
  }
}

i have also made one with Bootstrap - https://jsfiddle.net/4e8v5vrf/4/

hope that helps!

Upvotes: 0

Brian McNestry
Brian McNestry

Reputation: 155

So this is actually part of the basis of responsive design. So instead of using pixels for your table cell widths, use percentages. The percentages are based off the width of the element in which the table is contained. For example if it's in the body then this will be the width of the screen. If it's a div of width 400px or something then it'll be a percentage of that instead.

So change the width attribute to 33% if there's only 3 cells across for example.

dt {
    float: left;
    clear: left;
    width: 33%;
    margin: 0;
    padding: 10px;
    font-weight: bold;
}

dd {
   float: left;
   width: 33%;
   margin: 0;
   padding: 10px;
}

Upvotes: 0

Related Questions