开发者

How best to handle styles for nested h1's in html5?

开发者 https://www.devze.com 2023-01-28 21:35 出处:网络
I\'m currently working on some HTML5 themes for a few of my websites, and I keep running into problems with the way <h1>\'s can be used multiple times. I can\'t seem to predict in what elements

I'm currently working on some HTML5 themes for a few of my websites, and I keep running into problems with the way <h1>'s can be used multiple times. I can't seem to predict in what elements the headings will show up, but I do want to try and size them automatically based on their position in the DOM...

I was thinking about using something like

h1 { font-size: 3em; }
h2,
body > * > header h1 { font-size: 2.5em; }
h3,
body > * > header h2,
body > * > * > header h1 { font-size: 2em; }

But obviously that's far from waterproof. Having an extra element around an h1 that doesn't really mean it's deeper in the page structure will tend to 开发者_开发知识库pick way too small sizes. For example an unordered list with blocks that each have their own title will have something like

<section>
  <ul>
    <li>
      <header>
        <h1>Title of a block</h1>
      </header>
      content
    </li>
 </ul>
</section>

Which makes the <h1> appear much deeper than it actually is. What are good ways to handle this?


You should style the h1s based on the type of elements they are in, not just the depth.

For example, if you have general headings, article headings and sidebar item headings, you could do this:

h1 { font-size: 3em }
h2 { font-size: 2.5em }
article h1 { font-size: 2em }
article h2 { font-size: 1.5em }
aside h1 { font-size: 2.5em }

You would use whatever selector you use to select the articles or sidebar for layout (in my example, the article and aside tags, it might be section.sidebar or something else) to differentiate between different h1 tags.

There is not much of a connection between the depth of the tag, and the size (although there seems to be a pattern; deeper is smaller). There is however a connection between the convention used for marking up your sidebar, and the size of the headings in the sidebar. The CSS selectors for the headings will match up with the selectors for the layout, which shows the connection.


Firstly I'm a little unsure why you would need a

section -> ul -> li -> header -> h1

Why not just

section -> header -> h1

It seems like an interesting way to set up your styles, but also confusing and possibly unnecessary. I mean HTML doesn't mean the end of class and id, why not use:

body section.class{}
body section.class header h1{}

<section class="class">
 <header>
  <h1>Title</h1>
 </header>
 <content>
  <p>Content</p>
 </content>
 <footer>
  footer
 </footer>
</section>


It's not going to help you in any practical sense in the near future, but there is a proposal for CSS to make this sort of thing a bit cleaner, the any selector. The general rule for a second level heading would go from this:

section section h1, section article h1, section aside h1, section nav h1,
article section h1, article article h1, article aside h1, article nav h1,
aside section h1, aside article h1, aside aside h1, aside nav h1,
nav section h1, nav article h1, nav aside h1, nav nav h1, {
  font-size: 20px;
}

To this:

any(section, article, aside, nav)
any(section, article, aside, nav) h1 {
  font-size: 20px;
}


If you really can't tell where your h1 elements will appear you have a problem ...

You need to work into your stylesheets the places which affect the resolved level of the h1 in the outlining mechanism. These are the sectioning elements (article, aside, nav, and section) and the sectioning root elements (blockquote, body, details, fieldset, figure, and td)

The other elements don't affect the h1 level so they can be ignored, but might be wrappers like ul and li in your example so your css selectors should use descendent rather than child relationships.

Nevertheless, without building a stylesheet specifically for your page structure, the css rules set spirals out of control very quickly.

You want something like:

body h1 { font-size: 3em; }
body section h1 { font-size: 2.5em; }
body article h1 { font-size: 2.5em; }
body nav h1 { font-size: 2.5em; }
body aside h1 { font-size: 2.5em; }
body section section h1 { font-size: 2em; }
body section article h1 { font-size: 2em; }
body section nav h1 { font-size: 2em; }
body section aside h1 { font-size: 2em; }
body article section h1 { font-size: 2em; }
body article article h1 { font-size: 2em; }
  ...
  ...
  ...

And so on. Repeat for each sectioning root and for each of h1 to h6 and you have a massive css file.

Much easier if you know the structure of your page, at least for the sectioning and section root elements, then you can just write the rules for those combinations actually in use.


Another thing you could do would to use an id on the <h1> tag. For example, your HTML would be:

<h1 id="page-title">My Blog</h1>

And then in your CSS, you could use:

h1#page-title { font-size:2.5em; color:#f00; [etc] }

Update: It just got mentioned to me that this may be irrelevant info, so here's my two bits: so the nested <h1> isn't styling properly? This is how I'd fix it, by making it a unique identifier rather than specifying it with each nested tag.


HTML5 is supposed to make coding simpler and IMO you are taking the header and h1 thing way to far. They are both header tags so spamming both of them all over you page is just redundant.

A page should only have 1 <h1> tag, to show what the entire page is about, each section does not need an h1 tag like I said above

Regardless the easiest way would be to use classes and IDs, just like in the past.

<section class="widget">
  <ul>
    <li>
      <header>
        <h1>Title of a block</h1>
      </header>
      content
    </li>
 </ul>
</section>

Then you can remove all the extra selectors and they can be more generic.

section.widget h1 { }
section.something h1 { }


Firstly, according to the proper usage nested h1's should be treated exactly according to their significance of nesting (including article, aside, nav, section but not any other elements). This is correct behavior. An h1 nested inside a section element should be the same visually as an h2, and an h1 nested inside two section elements should be visually the same as an h3... Basically, in short, there's an alternative markup floating around that pretty much no-one uses but is really more semantically consistent which is to only use h1 ever, and allow the level of heading to be determined by the document outline.

authors are strongly encouraged to either use only h1 elements, or to use elements of the appropriate rank for the section's nesting level. per Section 4.3.11 of WHATWG

So, I believe you're on the right track with wanting this and I think the chosen correct answer is giving you subjective stylistic advice rather than attempting to answer your question, which is a valid one.

As far as implementation:

For webkit browsers (chrome and safari) and firefox you can use the "-moz-any" and "-webkit-any" css pseudoselectors. This is, in fact, how the default stylesheets in firefox and chrome style these elements perfectly according to the standards already:

For example, at level 3 headings in the firefox default css:

h3, *:-moz-any(article, aside, nav, section) *:-moz-any(article, aside, nav, section) h1 {
    display: block;
    font-size: 1.17em;
    font-weight: bold;
    margin: 1em 0;
}

This greatly simplifies the answer @Alohci rightly suggested.

The problem is, of course, it wont work in IE. One option is to use a CSS pre-processor, such as SASS. I have written the following snippet in SASS which I use to do my header markup and which I use to effectively normalize across browsers the presentation of nested h1 elements. (If you don't want to actively use a CSS pre-processor you can use one a single time to generate your initial template for these values and then modify the values as needed over time -- it will at least save you tons of typing and eliminate potential errors in the process):

@function bb_permute_lists($left_list, $right_list) {
    $permuted_list: ();

    @each $left_item in $left_list {
        @each $right_item in $right_list {
            $permuted_list: append($permuted_list, $left_item $right_item, comma);
        }
    }

    @return $permuted_list;
}

@function bb_html5_header_markup($level) {
  @if (1 == $level) {
    @return h1;
  }

  $header_containers: article, aside, nav, section;
  $header_markup: $header_containers;
  @for $i from 2 to $level {
    $header_markup: bb_permute_lists($header_containers, $header_markup);
  }
  $header_markup: bb_permute_lists($header_markup, h1);

  @return append(h#{$level}, $header_markup, comma);
}

This function can be used as follows:

#{bb_html5_header_markup(1)} { 
  font-size: 2em;
    margin: .67em 0;
}

#{bb_html5_header_markup(2)} { 
    font-size: 1.5em;
    margin: .83em 0;
}

Best of luck in trying to implement this alernative standard. There's plenty of documentation out there about this alternative and more-semantic usage of h1, but based on the fact that I could not find anyone else with a code snippet to help me along in implementing it, I think it's rather rarely used (perhaps because people are working with a lot of mixed content, whereas I am starting from scratch).

0

精彩评论

暂无评论...
验证码 换一张
取 消