Default :target with CSS

2019-01-06 19:17发布

问题:

I have this CSS:

<style type="text/css">
.tab {
  display: none;
}
.tab:target {
  display: block;
}
</style>

And this HTML:

<div class="tab_container">

  <ul class="tabs">
    <li><a href="#updates-list">List</a></li>
    <li><a href="#updates-map">Map</a></li>
  </ul>

  <ul class="tab list" id="updates-list">
    Eh.. Hello!
  </ul>
  <div class="tab map" id="updates-map"></div>
</div>

However, my page is empty if no target (# in URL) is specified and no tab is clicked yet. I want to show ul#updates-list by default.

How can I do this? Thanks.


Update: Next to this, my Google Map is broken if it is not the initial target. Does anyone know a fix?

回答1:

Spontaneously I'd have to say that the only solution I can think of is unfortunately using JavaScript. Something like:

<script type="text/javascript">
  if (document.location.hash == "" || document.location.hash == "#")
    document.location.hash = "#updates-list";
</script>

EDIT:

Ok, got a CSS solution. This however requires the default entry #updates-list to be placed last (after #updates-map and any other tabs you may add):

.tab, .tab:target ~ #updates-list  {
  display: none;
}
#updates-list, .tab:target {
  display: block;
}


回答2:

I know this is an old question, but it's still relevant and I have another suggestion:

<a href="#tab1">Tab 1</a>
<a href="#tab2">Tab 2</a>

<a id="tab1"></a>
<a id="tab2"></a>

<div class="tab tab1 default-tab">Some content</div>
<div class="tab tab2">Some other content</div>

and the css:

.tab {display:none}

.default-tab {display:block}

:target ~ .default-tab {display:none}

#tab1:target ~ .tab1,
#tab2:target ~ .tab2 {
  display: block
}

This lets you have the tabs ordered however you want, but if you're generating the html dynamically you'll need to generate the css dynamically. Or else choose a maximum number of tabs to support when you write the css.



回答3:

I guess what you would want to do is select something like .tab_container:not(> :target) > .default to display the default tab when no one is targeted. However, this is not possible since the :not() pseudo-class only takes simple selectors (i.e. just :target, not > :target, in which case you would check the target of the container, not the children).

I would do either of the following:

  • Use Javascript to set the target to the first tab at load (or just require that the anchor is present).

  • Add a specific override class for the first active tab and remove it (again with Javascript) after the first tab switch.

The first alternative will mess with the browser history while the second will be a bit more of a code mess. I can't think of a "perfect" solution right now. Maybe you're better off just using Javascript altogether to detect the current target in order to both get compatibility with non-CSS3 browsers and to solve this particular issue in a somewhat clean way?



回答4:

This seems to be the shortest answer I could find:

location=location.hash||"#updates-list"

This simply redirects the user to a valid hash if it is currently nonexistent or empty #.

~98% of users have JavaScript enabled, so a JS solution shouldn't really be a problem.



回答5:

Useful:

.tab#tabControl { display:block; }

.tab:not(:target) { display:none; }

.tab:target ~ #tabControl { display:none; }