2

I am working on the menu of a pretty old site. The site is still built in a <table>, so the whole code structure is a bit strange. I can't change the formatting itself, so the solution should ideally be CSS-only.

My menu is built like this:

<ul id="categorymenu">
  <li class="level1"><a href="#" title="...">Item #1</a></li>
  <li class="level1 active"><a href="#" title="...">Item #2</a></li>
  <li class="level2 active menuselected"><a href="#" title="...">Subitem #1 of Item #2</a></li>
</ul>

The <ul> has 6 levels, but they're not separated by sub-<ul>s, the styling is handled via the level classes.

When a menu item is selected, the classes active and menuselected are applied to the currently selected item. If I go deeper into the menu, the class active remains on the points where a new <ul> would have opened (i.e. the points where I go from one navigation level to the next).

The class menuselected is only applied to the currently selected item (along with the class active).


Using CSS, I've added arrows graphics to the menu. Non-active elements have a right-facing arrow, active elements have a down-facing arrow to symbolise the newly opened menu levels.

Here is my CSS:

ul#categorymenu li:not(.active):before {
  content: "";
  border-color: transparent #fff;
  border-style: solid;
  border-width: 0.55em 0 0.55em 0.55em;
  display: inline-block;
  height: 0;
  width: 0;
  left: -0.2em;
  top: 0.75em;
  position: relative;
}

ul#categorymenu li.active:before, ul#categorymenu li.menuselected:before {
  content: "";
  border-color: #fff transparent;
  border-style: solid;
  border-width: 0.55em 0.55em 0 0.55em;
  display: inline-block;
  height: 0;
  width: 0;
  top: 0.6em;
  left: -6px;
  margin-right: -6px;
  position: relative;
}

This works exactly as it should, except that the last element gets the wrong arrow.

If I click all the way through the menu, the last item will get the downward facing arrow (since it has both the classes active and menuselected).

What I'm trying to do is write a rule that says something like "apply the normal arrow to every item with the class menuselected that is not followed by a <li>-element with a different class than the current element".

DTX
  • 192
  • 1
  • 12
  • Do you have a JS Fiddle with that? – GreyRoofPigeon Sep 28 '16 at 10:46
  • 2
    In current CSS, there is no way to write such a selector. You can only look at elements before or above the one you are trying to target, but not in the opposite direction. // But the number of those fake “levels” is known to you beforehand and static, yes? Then you could simply exclude elements on the last level from being targeted by your selector in the first place (using `:not()` would be a simple way to do that.) – CBroe Sep 28 '16 at 10:48
  • 2
    I think you should consider changing the structure of your menu as it is not semantically correct. Also submenus down to six levels - I as a user would leave the site if I came across something like that – Pete Sep 28 '16 at 11:08
  • Could you consolidate the two stacksnippets into one, so that it becomes a working demo. – Mr Lister Sep 28 '16 at 11:24
  • The difficulties you are facing are directly attributable to the fact that the structure of your HTML does not correspond to its meaning. –  Sep 28 '16 at 12:22
  • 1
    like @CBroe said, you can do it in the forward directions, but not in the backward direction. Take a look at [Adjacent sibling selectors](https://developer.mozilla.org/en/docs/Web/CSS/Adjacent_sibling_selectors) to know how it works. – Alex Sep 28 '16 at 12:26

0 Answers0