Wednesday, January 11, 2017

Standard HTML elements (tags) does not have fixed visual presentation

I knew that some HTML elements (tags) like <div> or <span> does not have fixed visual presentation. They were designed to allow user to specify their view using CSS. But now I figured out that presentation of any HTML may be completely changed, even for such elements as <table>, <tr> and <td>. Here I'll demonstrate how you can completely change how your table looks like on small devices using just CSS.

There is a problem with wide tables on small devices. They just don't fit to screen. It would be much better to represent such a table as a list of "cards" if browser window is too narrow. Each card will contain information from one row, but arranged in convenient for small screen way.

Certainly we can solve this problem by generation of two pieces of HTML markup: one for wide screens and one for narrow screens. Then we will just hide one of them using CSS media queries. The problem with this approach is that we have to generate two different markups for the same information. It makes our HTML files big and ugly.

But can we do better? What if I have only one piece of markup for HTML table:

<table class="peopleTable">
    <thead class="peopleTableHead">
        <th class="peopleTableHeader">ID</th>
        <th class="peopleTableHeader">Name</th>
        <th class="peopleTableHeader">Company</th>
        <th class="peopleTableHeader">E-mail</th>
        <th class="peopleTableHeader">Phone</th>
    </thead>
    <tbody class="peopleTableBody">
        <tr class="personRow">
            <td class="personData"><span class="personDataValue">1</span></td>
            <td class="personData"><span class="personDataValue">Ivan Iakimov</span></td>
            <td class="personData"><span class="personDataValue">My company</span></td>
            <td class="personData"><span class="personDataValue">IvanI@mycompany.com</span></td>
            <td class="personData"><span class="personDataValue">8 987 654 32 10</span></td>
        </tr>
    </tbody>
</table>

Can I display it as "cards" on narrow screens?

Yes, I can. I can use the fact that HTML elements (tags) do not have fixed visual presentation. It means that I can make <table> tag look like <div> tag. All I have to do for it is just properly set 'display' property of style of this element. Look this CSS:

@media (max-width: 800px) {
    .peopleTable {
        display: block;
        border: 5px black solid;
    }
    
    .peopleTableHead {
        display: none;
    }
    
    .peopleTableBody {
        display: block;
    }
    
    .personRow {
        display: block;
        border: 3px red solid;
    }
    
    .personData {
        display: block;
    }
}

As you can see I make <table>, <tbody>, <tr> and <td> elements render like block elements. Now when I use small screens my table will look like a bunch of nested divs. I have effectively made a "card" from one row of table. I can now continue to augment my CSS definitions to make my "cards" look nice.

But there is another problem now. Names of columns completely vanished from all my "cards" on narrow screen. I'd definitely like to have them near data values on my "cards". For this reason I have to add them inside all my data cells:

<table class="peopleTable">
    <thead class="peopleTableHead">
        <th class="peopleTableHeader">ID</th>
        <th class="peopleTableHeader">Name</th>
        <th class="peopleTableHeader">Company</th>
        <th class="peopleTableHeader">E-mail</th>
        <th class="peopleTableHeader">Phone</th>
    </thead>
    <tbody class="peopleTableBody">
        <tr class="personRow">
            <td class="personData"><span class="personDataName">Id</span><span class="personDataValue">1</span></td>
            <td class="personData"><span class="personDataName">Name</span><span class="personDataValue">Ivan Iakimov</span></td>
            <td class="personData"><span class="personDataName">Company</span><span class="personDataValue">Confirmit</span></td>
            <td class="personData"><span class="personDataName">E-mail</span><span class="personDataValue">IvanY@confirmit.com</span></td>
            <td class="personData"><span class="personDataName">Phone</span><span class="personDataValue">8 987 654 32 10</span></td>
        </tr>
    </tbody>
</table>

Now I can hide them on wide screens and show them on narrow screens with CSS:

.personDataName {
    display: none;
}

@media (max-width: 800px) {


    /* other definitions */

    
    .personDataName {
        display: inline;
        font-weight: bold;
        margin-right: 1em;
    }
}

As you can see we have returned to the first solution in some sense. We generate different markup for different sizes of screens and show/hide it. It means that even if we can change visual presentation of different HTML tags it is not enough for modern responsible Web design. We still have to modify our markup to accomodate different devices.

No comments:

Post a Comment