0

The following problem happens when you style menus in Drupal, using CSS. The problem is especially dominant when you edit the <a> tags of a menu, but happens in regards to all of the menu markup.

The following images describe problems for two different menus, in which CSS directives I gave to my #navigation selector and its <a> tags, such as height: 60px, display: inline-block, and color: #fff, are inherited by the contextual links markup and thus destroy its appearance and making it impractical if not nonfunctional.

Thus, the solution I need is to separate the contextual links CSS from the themes', loading it afterwards or hardcoded somehow.

I dedicate this question to experienced themers: How can one load the contextual links with "hardcoded" CSS code, so they won't inherit anything from CSS directives I write in any theme-dependent CSS.

enter image description here

enter image description here

Code information:

Twig data:

{{ menus.menu_links(items, attributes, 0) }}

{% macro menu_links(items, attributes, menu_level) %}
  {% import _self as menus %}
  {% if items %}
    {% if menu_level == 0 %}
      <ul{{ attributes.addClass('menu') }}>
    {% else %}
      <ul class="menu">
    {% endif %}
    {% for item in items %}
      {%
        set classes = [
          'menu-item',
          item.is_expanded ? 'menu-item--expanded',
          item.is_collapsed ? 'menu-item--collapsed',
          item.in_active_trail ? 'menu-item--active-trail',
        ]
      %}
      <li{{ item.attributes.addClass(classes) }}>
        {{ link(item.title, item.url) }}
        {% if item.below %}
          {{ menus.menu_links(item.below, attributes, menu_level + 1) }}
        {% endif %}
      </li>
    {% endfor %}
    </ul>
  {% endif %}
{% endmacro %}

Mobile-first responsive CSS:

#navigation {height: auto; padding: 10px 0 10px 0; background: #0a97b7}
    #navigation ul {display: none} /*For JS conditioning: if none than...*/
    #navigation li {display: block}
        #navigation a {color: #fff}
            #navigation a:hover {text-decoration: none}
    .navtoggle {display: block; padding: 10px 25px 10px 0; font-size: 24px; background: none !important}

Desktop level CSS:

@media screen and (min-width: 1080px) {
    #navigation {height: 60px; padding: 0}
        #navigation ul {display: block}
            #navigation li {display: inline-block}
                #navigation a {height: 60px; line-height: 60px; padding: 0 15px 0 15px; display: inline-block}
                /*<a> must be either block/inline-block to have its height changed.*/
                    #navigation a:hover {background: #55cfd6; text-decoration: none}
    #navigation .menu-item {display: inline-block; float: right}
    #navigation .is-active {background: #55cfd6}
    .navtoggle {display: none !important}
}

Complete reset of the contextual links class as follows, isn't effective (nor it is adequate) and is overridden by more specific codes:

.contextual ul       {background: #fff !important}
.contextual li       {display: block !important}
.contextual a        {color: black !important; height: auto !important; line-height: 1.3em !important; background: #fff !important}
.contextual a:hover  {background: #f4f4f4 !important}

Every in-place menu seems better with this compelete reset, but it still don't cover all menus.

0

2 Answers 2

1
+50

If you do it like that #id a { ... } it will affect all the <a>'s of all the child divs that are inside the wrapper. Since the contextual links are inside it, they get affected.

enter image description here

Ex: if you do html a { color: purple;} since everything is a child of HTML, every single <a> gets affected.

In CSS there is no such command to affect all children except some child.

In CSS you have to affect all children, and then you can override a specific child by placing .somediv a { color: green; } after.

Ex:

html a { color: blue; } // all divs become blue.
.somediv a { color green; } // changes somediv to green.

If you do the same command:

a { color: brown; }
a { color yellow; }

It applies the brown first, but then applies the yellow. So the yellow is the actual one that you see. This is why it's called Cascading Style Sheets. It reads from the top to the bottom.

So in your case you currently have

.contextual a{ color: black; } // applies black 
#menu-id a{ color: orange; } // since contextual is inside #menu-id the orange gets applied, since this is last, you see orange on your screen.

Solution (In Theory):

You need to load the style sheet that contains the .contextual AFTER the style sheet that contains the #menu-id

So when your website loads, it will read like this

#menu-id a{ color: orange; } // contextual is orange because it's inside menu-id, so it inherits this command.
// bunch of other stuff in between
.contextual a{ color: black; } // contextual is black

Since black is last, you see black for contextual

But there is one problem, the /core/themes/stable/css/contextual/contextual.theme.css gets loaded before your theme. You would have to hack core so it loads this css file after your theme's .css file.

Alternative solution:

What you could do is find something that wraps around the tab only rather than something that wraps the entire menu, such as .menu-item

enter image description here

2
  • I know the hierarchy issue... I tried to duplicate contextual.theme.css to my sub-theme, and referenced to it from libraries.yml, then drush cr. Still no change, even this last-in-hierarchy file clashes with it's previous (the main sub-theme stylesheet).
    – user16289
    Sep 11, 2016 at 23:13
  • @Benia I will re-look at this later, but perhaps you also need to load the quick edit module css file after your theme.
    – No Sssweat
    Sep 11, 2016 at 23:20
1

All contextual links are wrapped in a div.contextual, whereas navigational menu items are usually wrapped in a li.menu-item.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.