In Basecamp’s early days “semantic HTML” was all the rage. It still is in some ways, but we were hitting the kool-aid a lot harder than we are today. One area where this has bitten us is in our default styles for the UL element.
When we started styling Basecamp we were mostly working with interface elements, not text documents. True to the semantic kool-aid we used UL tags mainly for tabs, category links, lists of project links, attached files etc. Everything but actual plain-jane bullet lists.
It all worked fine, but just now I wanted to include a bulleted list in some copy I’m sketching for a dialog. Check out how the unordered list looks in this draft using default styles:
That list in the middle is actually a UL. There are no bullets, the font size is wonky, the margins are different. This default must have made sense when all of our ULs followed a certain pattern for interface use. But here in the future, I wish we would’ve been more selective about those styles and left the default alone. Or better yet, we could’ve used DIVs in the first place for those tabs, attachments, and category links. I’ll surely keep this in mind the next time we start a fresh project.
Jim Jeffers
on 03 Jun 09Or you could just add a class to the UL and still keep the elements proper. I use a reset css on all of my projects and it causes this. It also helps me tons. To deal with it I add all of the essential styling for ol, ul, pre, blockquote, etc. but all of this is preceded by a class like .content. This way I retain all of my defaults via simple naming convention in my markup.
Also, I don’t understand your notion to use div’s in this example unless you want to punish disabled users.
Paulo Pereira
on 03 Jun 09Yeah, like Jim Jeffers said. You don’t need to compromise semantic HTML because of that. A proper use of CSS classes wouldn’t hurt a bit.
Nathan
on 03 Jun 09I’ve had this problem before, but now I tend to be more specific with my CSS rules. A list inside a paragraph might use default styles, while a list inside div#navigation might look very special.
That said, I do still find it to be problematic when nesting ULs, I find myself using divs more often for things that aren’t exactly lists but I would have used ULs for in the past.
Steve
on 03 Jun 09Styling the default as you want it as text, and applying a common class to any structural lists (reset margin & padding, remove bullets) has always seemed the best way round to me. That way anything that gets added by others (e.g. CMS) is styled properly.
Micheal
on 03 Jun 09Keep in mind, you don’t even need to add a “class” or even change your existing HTML.
Simply use CSS inheritance, where:
main ul { list-style-type: none} /* don’t display bullet / getUpdates ul { list-style-type: disc} / display bullet */This assumes you have a different parent DIV id
Tyson
on 03 Jun 09Given that 37signals has dropped support for IE6, why not just use the child selector as it was intended to be used?
ul.menu > li { bullets: nuke!; colors: crazy!;}
Etc.
To be honest, I think you’re attacking the right problem from the wrong angle. The solution isn’t to devise a new system to suit your needs, it’s to use the system that already exists that was designed to solve your needs.
Jonas Nicklas
on 03 Jun 09The true power of CSS comes from the descendant selector (and friends) instead of doing:
ul { some-style-for-tabs: wonky_value; }
it would be better to do:
tabs ul {some-style-for-tabs: wonky_value; }
and it wouldn’t have been a problem to use the list tag for either a list of tabs, or for a list of issues in an email. You just have to add the:
email ul {some-style-for-emails: ...; }
If styles start bleeding into each other it probably means that the selectors are too general. This is one of the reasons I like using SASS for CSS, as it makes it easier to nest tags.
Semantic markup not only conveys meaning to disabled users, but also to the person having to read the code later on. Markup with div-itis is harder to maintain, imho.
evan
on 03 Jun 09I don’t know Ruby On Rails but I bet there’s a way to add a class to a div, you should look into that
Micheal
on 03 Jun 09(Last post got mangled)
Keep in mind, you don’t even need to add a “class” or even change your existing HTML .
Simply use CSS inheritance, where:
main ul { list-style-type: none}
getUpdates ul { list-style-type: disc}
This assumes you have a different parent DIV id
RS
on 03 Jun 09Just to clarify, the point is that we made the wrong choice for our default styles for the UL. Going back and using a selector for everything like .nav ul { } etc is nice in theory but really difficult in practice when you’re inheriting all over the place from old defaults. That’s why I wanted to share this experience.
Andrew
on 03 Jun 09My guess is you have a global reset somewhere that is setting list-style and margin of the ul element…
steve
on 03 Jun 09You do need a class if the default list style has margin and bullets, otherwise every time you use a structural one (often lots) you have to remove margin/padding/bullets each time.
Brandon Durham
on 03 Jun 09Yeah, it’s rarely a good idea to set a default style for an element globally (unless it’s in a reset file), or even all UL’s in a #content DIV, for that matter. It’s ALWAYS bitten me in the end. Just forces you to be smarter about organization for the next project (and the next and the next).
N
on 03 Jun 09What many people don’t realize is that CSS is parsed from right to left by browsers. This causes much inefficiencies when doing:
.tabs ul { ... }
Browsers will look for ALL ul tags in the source and traverse upwards to find the parent “tabs” class.
I get what you’re trying to say Ryan. Thanks.
Brandon Durham
on 03 Jun 09I can understand your pain, though. You learn SO MUCH with every new project that it’s often inherently painful to revisit old work. I’m so OCD that I always want to completely revamp old work when I have to visit it.
Jo Potts
on 03 Jun 09That’s so funny. I rejigged my CSSs to make my ULs bullet by default litterally 5 minutes before reading this. A lot of the joy of coding is in the refactoring.
Stephen L
on 03 Jun 09@Ryan
If the problem was with the default UL styles, why do you state that “better yet, we could’ve used DIVs in the first place for those tabs, attachments, and category links”?
The appropriate response to a failing in your CSS would be to modify the CSS styles causing you problems, not change the HTML elements to which they apply.
Stephen
George
on 04 Jun 09I tend to give all UL menus the class name “nav”, after the HTML5 element, and don’t use any default style for ULs that will conflict with normal usage.
All ULs that are used for menus, navigation, etc. should have their own class names to avoid this problem.
Plain old semantic usage of class names is all you need, and not going berserk with default styles.
Jethro Larson
on 04 Jun 09Using UL before wasn’t wrong and isn’t wrong now. The mistake was breaking the base semantic case (a bulleted list) to achieve the tangential one (navigation list).
I use class-based html5 for stuff like nav and sections and such. It’s worked well. So if I mean it becomes
Make sure any tags that could be used in copy retain their original styles at least. Copy editors don’t want to worry about what the styles are for common elements so the standardista has to look out for them.
Jethro Larson
on 04 Jun 09Ack, tags got stripped. what I meant to say was:
So if I mean <nav> it becomes <ul class=”nav”>
Jim Jeffers
on 04 Jun 09@rjs – I think the problem is that we as front end architects lack any ability to ‘test’ our css code. In rails we can create unit tests or specs that, if written properly, allow us to refactor our code with confidence. How exactly can we do that for our css? I don’t think there is a solid answer here. It’s possible that we could creaye static pages with all of our apps widgets that we can load to QA our css modifications. Or possibly a series of layouts that we must review in order to give our updated css a pass. But of course we still have cross browser worries. I think it’s more of a css issue than a semantic problem. There’s no easy way.
The best solution? Incorporate conventions early on, keep your html markup semantic and lightweight, and always keep it simple. The inheritance problems normally are a result off too many nested elements that were used to patch some holes in the ui implementation. My experience has shown me more complex css is easier to manage than more html markup madness.
Bartek
on 04 Jun 09I have a solution that works for me (and have been for the last couple of years) and may as well work for you.
You can keep the reset on uls and you don’t have to put add a class to your lists in the content containers (define content container as the element where you put your HTML content [aka. copy, formatted text]).
Just add a class to the content container itself. I use a short class name, like “ed” (from “editor”). I mostly use it on elements that wrap HTML created by the user, often with a WYSIWYG editor.
So now you keep your generic reset:
ul { list-style: none; }
But you add something like this:
.ed ul { list-style: square outside; ... }
The latter overrides your reset. Now you only have to add the “ed” class to your content container (probably a div).
It works quite nicely. You end up with something like:
.ed ul { ... } .ed p { ... } .ed h4 { ... } .ed h5 { ... }
etc. I sometimes put all these rules into another CSS file, for example editor.css, and then @import it into the main stylesheet.
I’m a webdeveloper and I could not stand non-semantic, div-only markup, but this solution allows me to use lists and other elements and makes me very few problems. Just add an ed class here and there, it’s really not that much work… If you had to add a class to every single list and paragraph used as content, now that would be a pain.
Joe Clark
on 04 Jun 09Dude, give it up. #navbar ul ≠ #body ul.
Shorter 37 Signals: If we had to do it all over again, we would have done an even worse job.
Daniel Haran
on 04 Jun 09I drank the kool-aid so much I even created the semantic-menu plugin (shameless plug, linked above).
While I understand the pain you’re trying to deal with, the solution you’re proposing – using divs next time – is only going to punish blind users. Keep the semantics, and don’t override UL’s default style!
Thijs
on 04 Jun 09I feel this has absolutely nothing to do with semantic html. There was a problem in how you structured your css, not in using the ul element for this list.
roger wilco
on 04 Jun 09I always felt that one annoying trend of evangelical semantic HTML purists was using ULs for everything. That said, I don’t think semantic HTML was a fad as much as it was a welcome direction in coding markup.
Roy
on 04 Jun 09I’m actually pretty shocked by this post. It’s so… not 37signals. Why would you want to fix stupid CSS by throwing stupid HTML at it?
Steven Krein
on 04 Jun 09wow- what happened to that feature? Daily Digest in your email? that would be great!
Craig
on 04 Jun 09When has using global defaults/settings in anything ever been a good practice?
Be it: programming (using global variables), or in writing (making global generalizations)
Alejandro Moreno
on 04 Jun 09This has been said before, but I’m pointing it out again because the post carries a negative tone toward semantic HTML.
Semantic HTML is not at fault. The fact that UL is the more meaningful tag for tabs, navs, etc., does not mean that you have to use or change the default UL look.
There. Back to your scheduled programme.
RS
on 04 Jun 09Amen! I feel the same way.
Rich
on 04 Jun 09What’s a good resource (online or dead tree) that could help me follow this discussion (both in terms of CSS fundamentals, and best practices)? It’s the latter-best practices-that oftem seems to be the hardest to find.
RF
on 05 Jun 09Experience convinced me that “reset” stylesheets that take away the default appearance of tags aren’t good, mostly because they mess with any HTML that wasn’t specifically made for your stylesheets; many real-world apps have to deal with that. The base stylesheet should fix what discrepancies it can between the browsers’ default sheets, and when you remove bullets from lists, make strong and b nonbold, etc., it should be with classes, not by default.
Designers can also forget that semantic markup should mean more than avoiding presentational HTML; it should mean clear, meaningful markup. I don’t love it when, for example, the span tag has a magical new effect in a certain context, and there’s no class or other indication in the markup of the particular role of the content in the span.
I’ve even seen a designer control a list’s bulleting from JavaScript on the theory that it was purer: hey, you might have to edit an outside file whenever you add an item to this list, but it’s “semantic”!
Keith
on 05 Jun 09wow, i’m surprised that no one has really commented on how your showing us an unreleased feature, daily digest emails.
This would be great for many people on my team, hope to see it soon.
Graham
on 05 Jun 09Seriously dude… Your high horse called. He asks that you please get off of him.
Its not 2003 anymore people. Stop chugging the “ul’s equal rainbows for blind people” koolaid.
And before anyone accuses me of (GASP) using tables, please know that I have a blind coworker (a developer actually) that uses most of the apps I build, and I’ll guaran-damn-tee you that using a div instead of a ul does not even REGISTER on her list of things to complain about.
Conor
on 08 Jun 09It is not about div’s versus ul’s, its about a mistake on your part to override the default, instead of extending it. You attacked the semantic markup concept. When you should have been saying we made a bad decision, and now we have to live with it.
@graham I saw a presentation done by a blind dude in FOWA a few years ago. Stuff like this matters. Making life a little easier is important.
Amen to the dude who spoke about the testing concept. It would be nice.
This discussion is closed.