I like Excel for the ability to copy the whole column, and HTML tables don’t normally provide that. As a result, tons of time and nerves spent on copying cell by cell, cell by cell…
My friend and colleague (who btw likes HTML tables but in Adobe Dreamweaver graphic mode) needs a lot of data searched and sorted and put in table, but also copyable. Hm…
So, let’s make HTML tables great!
sidenote In my examples, tables are light blue
, and cells are pink
.
Option 1: Tables as columns
You can craft your own table out of a series of tables with float: left;
style:

<style>
td {
border: 2px solid pink;
}
table {
border: 2px solid lightblue;
}
</style>
<table style="float: left">
<tr><th>Phrases</th></tr>
<tr><td>I am keen on kinship.</td></tr>
<tr><td>This toad is tedious.</td></tr>
<tr><td>Your blouse is a blasphemy.</td></tr>
</table>
<table style="float: left">
<tr><th>Translations</th></tr>
<tr><td>Мне нравится родство.</td></tr>
<tr><td>Эта жаба утомительна.</td></tr>
<tr><td>Твоя блузка это богохульство.</td></tr>
</table>
Reference
Option 2: Flex style div
You can make columns out of <div>
elements, where the ‘table’ <div>
will have style="display: flex;"
and ‘column’ <div>
will have style="flex: 1;"
. I added some glam for beauty.

<style>
.child {
flex: 1;
margin: 5px;
padding: 10px 20px;
}
</style>
<div style="display: flex;">
<div class="child" style="background: pink;">
pink<br>
red
</div>
<div class="child" style="background: lightblue;">
<div>blue</div>
<div>azure</div>
</div>
<div class="child" style="display: flex; background: lightgreen;">
<div class="child" style="background: green; color: white;">
green<br>
leafy</div>
<div class="child" style="background: teal; color: white;">
teal<br>
turquoise
</div>
</div>
</div>
I also added a green column to show that flex can make infinite amount of columns inside other columns. You can make rows with <br>
or by wrapping each row in a column in another <div>
.
Reference
- My dear friend who refuses to start her own blog (her: cheers, sweetie)
Small Django example
Default data
Say, you have a QuerySet (in views.py):
context['persons'] = Person.objects.all()
With fields name
and nickname
(in models.py):
class Person
name = models.Charfield(max_length=255)
nickname = models.Charfield(max_length=255)
Normally you would organize a table like this (in html template):
<table>
<tr>
<th>Name</th>
<th>Nickname</th>
</tr>
{% for person in persons %}
<tr>
<th>{{ person.name }}</th>
<th>{{ person.nickname }}</th>
</tr>
{% endfor %}
</table>
But you would get a normal table with uncopyable columns. To transform it, in views.py you need to transform the QuerySet.
Copyable
New view
In views, make new context values for every column:
persons = Person.objects.all()
names = [x.name for x in persons]
nicknames = [x.nickname for x in persons]
context['lists'] = [['Names', names], ['Nicknames', nicknames]]
There are copious amount of way to do that. To not go through the object for time multiplied by amount of fields, you can do something like that:
results = [['Name', []], ['Nicknames', []]]
for x in results:
results[0][1].append(x.name)
results[1][1].append(x.nickname)
Or since we have column names, use dictionary instead of list:
results = {'Name':[], 'Nicknames':[]}
for x in results:
results['Name'].append(x.name)
results['Nickname'].append(x.nickname)
Final HTML
And html will look like this (with Option 1: Tables as columns):
<style>
td {
border: 2px solid pink;
}
table {
border: 2px solid lightblue;
}
</style>
{% for header, list in lists %}
<table style="float: left">
<tr><th>{{ header }}</th></tr>
{% for elem in list %}
<tr><td>{{ elem }}</td></tr>
{% endfor %}
</table>
If you are using dictionary, change this line (add .items
):
{% for header, list in lists.items %}