HTML/CSS source feedback


#1

Hi all,
I’m experimenting with basic layout in HTML/CSS using floats before I start studying flexbox and grid.
I took a cookie box and redesigned the nutrition label in HTML/CSS. Visually, aside from the font choice, the label is a passable reproduction of the original.

I’m looking at this as a newb, but my source seems a little dense for something that should be simple. I didn’t use tables because I thought I might have problems with the left margin and border length between the subnutrients (non-bold nutrients such as Sugars).
My question is, are my markup and styles too sloppy or unnecessarily complex?
Here is a browser screenshot in Chrome.


Here is my source.

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Nutrition Label</title>
        <meta charset="utf-8" />
        <style>
.nutrition-label {
    font-family: Verdana, Geneva, Tahoma, sans-serif;
    width: 14em;
    padding: .5em;
    border: 1.25px black solid;
}
header.nutrition-header {
    border-bottom: solid black 4px;
}
.nutrition-header .portion-size {
    padding: .2em 0;
}
header h1 {
    font-size: 1.5em;
    margin: 0;
}
.category-headings {
    font-weight: bold;
    font-size: small;
    text-align: right;
    border-bottom: 2px solid black;
    padding: .2em 0;
}
/* category clearfix */
.category-headings:after {
    content: " ";
    display: block;
    visibility: hidden;
    clear: both;
}
.category-amount {
    float: left;
}
.category-dv {
    float: right;
}
.nutrient {
    clear: left;
    border-bottom: solid black 1px;
    padding: .2em 0;
    text-align: right;
    position: relative;  
}
/* nutrient clearfix */
.nutrient::after {
    content: " ";
    display: block;
    visibility: hidden;
    clear: both;
}
.nutrient .nutrient-name {
    float: left;
}
.nutrient:last-child {
    border-bottom: 4px black solid;
}
.subnutrient {
    font-weight: normal;
    margin-left: .8em;
    border-bottom: 1px solid black;
    text-align: right;
    position: relative;
    padding: .2em;
}
.subnutrient-name {
    float: left;
    text-align: left;
}
.subnutrient:last-child {
    float: left;
    text-align: left;
    border-bottom: 0;
}
/*subnutrient clearfix*/
.subnutrient::after {
    content: "";
    display: block;
    clear: both;
    visibility: hidden;
}

.daily-value {
    position: absolute;
    right: 0;
    top: 25%;
}
.vitamin {
    clear: left;
    border-bottom: solid black 1px;
    padding: .2em 0;
}
footer {
    font-size: small;
}

        </style>
    </head>
    <body>
        <div class="nutrition-label">
            <header class="nutrition-header">
                <h1 class="nutrition-title">Nutrition Facts</h1>
                <div class="portion-size">Per 2 wafers (25 g)</div>
            </header>
            <main>
                <div class="category-headings">
                        <div class="category-amount">Amount</div>
                        <div class="category-dv">% DV*</div>
                </div>
                <section class="nutrients">
                    <div class="nutrient">
                        <div class="nutrient-name"><strong>Calories</strong> 130</div>
                    </div>
                    <div class="nutrient">
                        <div class="nutrient-name"><strong>Fat</strong> 7 g</div> 
                        <strong>11</strong>%
                    </div>
                    
                    <div class="subnutrient">
                            <div class="subnutrient-name">Saturated 5 g<br/>+ Trans 0 g</div>
                            <div class="daily-value"><strong>26</strong>%</div>
                    </div>
                    
                    <div class="nutrient">
                        <div class="nutrient-name"><strong>Cholesterol</strong> 0 mg</div>
                    </div>
                    <div class="nutrient">
                        <div class="nutrient-name"><strong>Sodium</strong> 15 mg</div>
                        <strong>1</strong>%
                    </div>
                    <div class="nutrient">
                        <div class="nutrient-name"><strong>Carbohydrate</strong> 16 g</div>
                        <strong>5</strong>%
                    </div>
                    
                        <div class="subnutrient">
                            <div class="subnutrient-name">Fibre 0 g</div>
                            <strong>0</strong>%
                        </div>
                        <div class="subnutrient">
                            <div class="subnutrient-name">Sugars 12 g</div>
                        </div>
                    
                    <div class="nutrient">
                        <div class="nutrient-name"><strong>Protein</strong> 1 g</div>
                    </div>
                </section><!-- nutrients end -->
                <section class="vitamins">
                    <div class="vitamin">
                        Vitamin A
                        0 %
                    </div>
                    <div class="vitamin">
                        Vitamin C
                        0 %
                    </div>
                    <div class="vitamin">
                        Calcium
                        2 %
                    </div>
                    <div class="vitamin">
                        Iron
                        4 %
                    </div>
                </section><!-- vitamins end -->
            </main>
            <footer>
                * DV = Daily Value
            </footer>
        </div><!-- nutrition label end -->
    </body>
</html>

#2

Hey @austen nice work! Cool idea to take something like a nutrition label to sharpen your skills. It looks really cool. For me your code looks good. I think CSS and HTML always has the tendency to look sloppy or complex. When I look at your code I can’t see some unnecessarily complex thing, every tag you wrote has it’s well design purpose. And in the CSS you use the cascading feature, that means you don’t repeat yourself there. Good.

But, I really don’t want to be annoying, a table would have been the right thing to go for this. Because… it really is a table :slight_smile:

With HTML we have that semantic thing and you should try to reflect your meaning in the markup.

For an exercise in float and CSS it is very well done, I would say.


#3

Well done, Austen! I agree with Didier, remake it with tables, just to dissipate that fear of margins :smiley:
Good habit would be to always keep your css in a different file. Get used to this simple practice.


#4

Thanks for the feedback. Here’s an updated version using tables. I gave up trying to fine-tune the layout. Specifically, although I got the indent-margin working, I couldn’t figure out how to get the subnutrient underline to extend to the right end of the table. I tried a bunch of approaches (including underlining the %VQ cells), but nothing fit right (alignment issues, etc.).


Here’s the markup.

<!DOCTYPE html>
<html lang="fr">
    <head>
        <title>Étiquette Nutritionelle</title>
        <link rel="stylesheet" type="text/css" href="tablelabelstyles.css" />
        <meta charset="utf-8" />
    </head>
    <body>
        <div class="nutrition-label">
            <header>
                <h1>Valeur nutritive</h1>
                <div class="portion-size">pour 2 biscuits (30 g)</div>
            </header>
            <main>
                <table class="nutrition-table">
                    <tr class="amount-header">
                        <th><small>Teneur</small></th>
                        <th class="dv-header"><small>%VQ*</small></th>
                    </tr>
                    <tr>
                        <td class="nutrient" colspan="2"><strong>Calories</strong> 150</td>
                    </tr>
                    <tr class="nutrient">
                        <td><strong>Lipides</strong> 7 g</td>
                        <td class="nutrient-dv"><strong>11</strong> %</td>
                    </tr>
                    <tr class="subnutrient">
                        <td class="subnutrient-amount" colspan="2">satures 4 g<br/ >+ trans 0 g</td>
                        <td class="subnutrient-dv"><strong>20</strong> %</td>
                    </tr>
                    <tr class="nutrient">
                        <td class="nutrient" colspan="2"><strong>Cholesterol</strong> 5 mg</td>
                    </tr>
                    <tr class="nutrient">
                        <td class="nutrient"><strong>Sodium</strong> 60 g</td>
                        <td class="nutrient-dv"><strong>3</strong> %</td>
                    </tr>
                    <tr class="nutrient">
                            <td class="nutrient"><strong>Glucides</strong> 20 g</td>
                            <td class="nutrient-dv"><strong>7</strong> %</td>
                        </tr>
                    <tr class="subnutrient">
                        <td class="subnutrient-amount" colspan="2">Fibres 1 g</td>
                        <td class="subnutrient-dv"><strong>4</strong> %</td>
                    </tr>
                    <tr class="subnutrient">
                        <td class="subnutrient-amount" colspan="2">Sucres 1 g</td>
                    </tr>
                    <tr class="nutrient last-nutrient">
                        <td colspan="2"><strong>Proteines</strong> 2 g</td>
                    </tr>
                    <tr class="vitamin">
                        <td>Vitamine A</td>
                        <td class="vitamin-dv">0 %</td>
                    </tr>
                    <tr class="vitamin">
                        <td>Vitamine C</td>
                        <td class="vitamin-dv">0 %</td>
                    </tr>
                    <tr class="vitamin">
                        <td>Calcium</td>
                        <td class="vitamin-dv">2 %</td>
                    </tr>
                    <tr class="vitamin">
                        <td>Fer</td>
                        <td class="vitamin-dv">6 %</td>
                    </tr>
                </table>
            </main>
            <footer>
                <small>* VQ = valeur quotidienne</small>
            </footer>
        </div><!-- nutrition label end -->
    </body>
</html>

And the stylesheet

* {
    outline: 0px blue solid;
}
.nutrition-label {
    font-family: Verdana, Geneva, Tahoma, sans-serif;
    border: 1.5px solid black;
    padding: .5em;
    width: 14em;
    text-align: left;
}
.nutrition-label header {
    padding: 0;
    padding-bottom: .25em;
    margin: 0;
    border-bottom: 4px black solid;
}
.nutrition-label header h1 {
    font-size: 1.5em;
    padding: 0;
    margin: 0;
}
.amount-header {
    border-bottom: 3px solid black;
}
.dv-header {
    text-align: right;
}
.nutrition-label main table {
    width: 100%;
    border-collapse: collapse;
}
.nutrient, .vitamin {
    border-bottom: 1px solid black;
}
.last-nutrient {
    border-bottom: 3px solid black;
}
/* subnutrient clearfix */
.subnutrient::after {
    content: " ";
    visibility: hidden;
    clear: both;

}
.subnutrient-amount {
    float: left;
    margin-left: 1em;
    border-bottom: 1px solid black;
    width: 100%;
}
.subnutrient-dv, .vitamin-dv, .nutrient-dv {
    text-align: right;
}

#5

wait a second, will come back with an answer.
Ok, if you want it to look like in my screenshot, do:
.subnutrient {
border-bottom: 1px solid black;
}

and nuke the bottom border from the .subnutirent-amount.
You have 2 elements there. The border of an element extends the length of that element. This is why you need to go one step above and add a border to the row that contains both elements if you want that border to underline them both.

Screenshot%20from%202018-12-21%2010-28-07

In HTML5 you don’t need the ending slash for void elements (img, link etc)
Those are strictly needed for XHTML:
https://www.456bereastreet.com/archive/201005/void_empty_elements_and_self-closing_start_tags_in_html/
Now, for accessibility reasons, it’s not good practice to not define what happens to the putline on :focus.
So you better do:
a:active {outline:none;} instead of: outline: 0 etc.
This way those that only use keyboard will still have the default outline for the :focuse state.
There are many tricks out there, but this is the cleanest.
Instead of:
padding: 0;
padding-bottom: .25em;

do:
padding: 0 0 0.25em 0;
Think of the element like of a square or rectangle. The sides come in order, clockwise: top, right, bottom, left.


#6

@io_io!! Thanks so much for going to the trouble of reviewing my code. I’ll definitely use the clockwise padding declaration next time. Also, I should’ve removed the outline declaration. It was only there for debugging purposes.

One thing I didn’t like when I was writing the table markup is that I had to consolidate nutrient names with their amounts in a single column/cell. e.g. “Lipides 7 g”. Ideally, the 7g would’ve been in its own column, but that would’ve completely broken the layout (ie, it wouldn’t have resembled the print version at all).

Your .subnutrient border solution seems like the most elegant option considering the limitations. It definitely looks better than mine.

All said, I now understand why tables are generally more semantically accurate than divs. Conversely, in terms of positioning and rendering, the options seem more constrained than what’s possible with nested divs. I guess if I need to accurately reproduce a print layout in html5/css, I should use nested divs for their flexibility, but if I need to avoid nesting and make my data accessible via assistive technology (or maybe even for scraping back into a database), tables are the way to go. I also learned that table layout is much faster to use than nested divs if I don’t try to make the tables do things they aren’t meant to do. :slight_smile:


#7

That’s exactly the spirit, Austen!
Way to go! HTML + CSS are huge, so you need some time and patience.
And when you are not sure of something, do what the big boys in the field do :smiley:
I mean those publicly recognized, like Andy Clarke, Lea Verou, Rachel Andrew etc ( I follow them all on Twitter)
They are real professionals and care a lot about both design and accessibility.


#8

Thank you @austen for your examples and sharing your experiences. There was a time when all websites were designed with tables. Luckily CSS came around to fix this. It is really big what you can do with HTML and CSS.

What I really didn’t recognized before your post is, that layout software like InDesign, QuarkXpress and Scribus use the same technique from your first example. They structure the print layouts with XML (instead of HTML) and style the elements with some kind of CSS-like language. So what you said about using the div approach to reproduce soemthing exactly you are absolutely on the right path.

@io_io thank you for the names. Will look them up :slight_smile:


#9

Awesome work @austen, I may have to steal this idea and finally learn modern CSS too.