I'm trying to theme my menu to alter the default UL classes. So far I'm working with the following function:
function theme_menu_tree($variables){
return '<ul class="my-class">' . $variables['tree'] . '</ul>';
}
This works great but I need to apply a different class to the UL inside a parent item. Right now I get
<ul class="my-class">
<li class="dropdown">Item
<ul class="my-class">
<li>Link1</li>
<li>Link2</li>
</ul>
</li>
</ul>
How can I target the second UL to give it a different class using the theme_menu_tree function?
Why do you need to override the menu class? Why not look at the CSS id or class of the body, section, or block that the menu is in and use that of where you are at and use that to override it?
For example, I'm using this to override the default appearance of a leaf menu item in a block:
#block-menu-menu-top-navigation ul li.leaf
{
list-style-type: none;
list-style-image: none;
}
In Drupal, there is no such thing as default UL classes. There are theme functions (recognizable by the function name starting with theme_) and templates (recognizable by the filename ending with .tpl.php). Neither makes any assumptions about what HTML elements are used to render the data. Especially, Drupal makes no assumptions about which classes should be applied to the elements that a template or theme function produces.
Maybe you are looking for the Menu attributes module. It lets you define CSS class and ID.
Related
I'm working on a navigation bar. One of my navigation items has a dropdown. For this item, I want to disable the normal link behavior (I have already done this with jQuery) and just have it open a dropdown with three functioning links on hover.
All of this is working functionally, but I have some trouble with the styling.
Note that I'm using a CMS that automatically generates the navigation, so I can't use an id to target the relevant menu item.
My menu looks like this:
<ul class="header-navigation-list">
<li class="header-navigation-list-item">
<a class="header-navigation-link primary-link" href="...">Home</a>
</li>
<li class="header-navigation-list-item">
<a class="header-navigation-link primary-link" href="...">About</a>
</li>
<li class="header-navigation-list-item has-dropdown">
<a class="header-navigation-link primary-link" href="...">Products</a>
<ul class="header-navigation-list secondary-list" data-is-dropdown>
<li class="header-navigation-list-item secondary-list-item">
<a class="header-navigation-link secondary-link" href="...">Product #1</a>
</li>
<li class="header-navigation-list-item secondary-list-item">
<a class="header-navigation-link secondary-link" href="...">Product #2</a>
</li>
<li class="header-navigation-list-item secondary-list-item">
<a class="header-navigation-link secondary-link" href="...">Product #3</a>
</li>
</ul>
</li>
<li class="header-navigation-list-item">
<a class="header-navigation-link primary-link" href="...">Blog</a>
</li>
<li class="header-navigation-list-item">
<a class="header-navigation-link primary-link" href="...">Contact</a>
</li>
</ul>
The goal is to remove all link-styling from "Products", but keep the link styling for "Products #1 - #3".
I tried targeting it via several CSS rules like .header-navigation-list > .has-dropdown or .header-navigation-list > .has-dropdown:first-of-type or .header-navigation-list > .has-dropdown a:first-child. The problem is that every time I manage to target the "Products" point, I also target all the elements it contains and disable the link-styling for "Product #1 - #3" too.
The second example below might be what you're looking for (jsfiddle: https://jsfiddle.net/pk8gsh9z/):
/**
* Example 1
*
* Targets the direct links of top-most LIs when all of the following are true:
* - they have a "has-dropdown" class.
* - they don't have a "secondary-list-item" class.
*/
.header-navigation-list .has-dropdown:not(.secondary-list-item) > a {
color: brown;
text-transform: uppercase;
}
/**
* Example 2
*
* Targets the direct links of the third LI when all of the following are true:
* - it has the "has-dropdown" class
* - and it doesn't have "secondary-list-item" class
*/
.header-navigation-list .has-dropdown:not(.secondary-list-item):nth-child(3) > a {
color: green;
}
General recommendation
A general thumbrule when writing CSS selectors is to keep the amount of rules at a resonable level for several reasons:
Readability: one should be able to understand what the class does by reading its name
Unified language between team members. Everybody knows what to expect from a class.
Maintainable code: your selectors do not unexpectadly break the website at an unknown place .
A good way to do this is by using the BEM naming convention
Your case
However, since you do not seem to be in the position to decide what classes or ids you use, you have to work with what you have.
This solution is very general:
.has-dropdown > .primary-link{
/*Reset styles goes here*/
}
It selects all elments where the direct children of .has-dropdown is the .primary-link class. For more information see Mozillas documentation on relationship selectors.
More specific CSS selectors
One example using the :nth-child selector could be:
.header-navigation-list > .has-dropdown:nth-child(3) > .primary-link{
/*CSS rules*/
}
THIS IS HOWEVER BAD PRACTICE due to readability problems.
Short summary
Whenever possible, choose your own classes, preferably according to a naming convention. If working with a CMS you might want to edit any theme files, but unless you plan to provide support for a long time, I would not recommend it.
Try to fully understand how to use CSS selectors and pseudo-selectors, to know what elements the styles will be applied to.
Workaround CMS Styles by Class
Isolate and identify targets. Primary are last in line. Secondary are Primary's ancestors (i.e. parents, parent's parent (grandma), etc.)
Primary Targets
Product #1 to #3: li.header-navigation-list-item.secondary-list-item
Secondary Targets
Products: li.header-navigation-list-item.has-dropdown (Grandma)
[Secondary List]: ul.header-navigation-list.secondary-list(Mom)
Determine what classes they all have in common. Find out what the style properties they have. These classes are untouchable because they are universally shared with every <ul> and <li>.
All <ul> have .header-navigation-list
ul.header-navigation-list {background: black; color: yellow;}✱
All <li> have .header-navigation-list-item
li.header-navigation-list-item no assignment it inherits instead ✱
✱ I have no idea what the styles are I arbitrarily assigned them.
Determine unique classes or secondary classes that are not shared with every <ul> or <li>
Primary Targets
Product #1 to #3: .secondary-list-item
Secondary Targets
Products: .has-dropdown
[Secondary List]: .secondary-list
That looks like 3 hooks all ready.
Given that we have no idea what the real situation is like the surrounding layout, all of the stylesheets, plugins, etc. Remember, navigation list layouts almost always have each anchor as an only child with the exception of a dropdown anchor (i.e. li.has-dropdown > a.primary-link), so it's easier to target the <li> first then step down to the anchor's level. Because inheritance, you should always style ancestors first then specifically style the children to override inherited styles. The possible selectors could be:
li.has-dropdown > a.primary-link { color:red; font-size:48px; }
li.has-dropdown > ul > li > a { color: yellow; font-size:48px; }
If you still have problems, go back to step 2 and counter-style those universal classes:
If you find this:
ul.header-navigation-list {background: black; color: yellow;}
Counter style it:
ul.header-navigation-list.secondary-list {background:none; color:transparent; }
li.header-navigation-list-item.secondary-list-item > a { background: white; color:blue; }
I've made dropdown using angular-ui-bootstrap
public/partials/partial2.html
<ul ...
<li class="dropdown" dropdown>
<a href="admin/partial2" role="button" class="dropdown-toggle" dropdown-toggle> brand list </a>
<ul class="dropdown-menu" role="menu">
<li>.....
</ul>
obviously href="admin/partial2" route(by angular-route) to same partial page( so same entire page ) and do nothing
but I need hand emoticon when user put mouse-over the anchor
Can I have this effect without specifying "href" attribute?
Yes, use css for that, create a rule for your anchor class (dropdown-toggle) in this case as follows:
.dropdown-toggle:hover {
cursor: pointer;
}
you can use <a> without href, but it's just like a spam inside your script.
For example, you have a text inside the div or, say, span, as in:
<span>Sitemap</span>
or, you have <ul> <li> in your dropdown menu, then you can add NEW Selector in your stylesheet(or CSS).
for example:
.mymenu li {
cursor:pointer;
}
From the code, I can explain that, you just need cursor:pointer, to make it happen. that's all.
if you set the cursor inside li, all li's will have that pointer.
to make it specific, I mean, if you need the pointer for only one scope, say, menu or dropdown menu where li or ul is used, you can add new selector then.
please check first the demo on plnkr.
My problem is: this animation will be applied to all elements in html,
cause in css is defined .ng-enter .ng-leave etc.
I am trying to apply it to a specific class name. In my case, it's <li class="specific">
And in CSS I've tried following:
.specific.ng-enter /*(does not work)*/
.specific-ng-enter /*(does not work)*/
With these code above, I can add and remove items but without animation.
How should the code be in css ?
Actually, there are a couple of possible issues with the code:
You are using ngRepeat on your <ul> (I cannot be 100% sure that this is not what you want but it is highly improbable). ngRepeat will "repeat" (clone" the element it is on, so in your case you are creating multiple <ul> elements (instead of multiple <li> elements, as one would expect).
Moving ngRepeat o the <li> will solve the animation problem and result in the intended HTML code (1 <ul>, multiple <li>).
Your CSS defined transition with every class, while it would suffice to define one rule:
.top.ng-enter, .top.ng-leave {
// ...define transitions here
}
In order to avoid possible CSS specificity issues (especially later on, when your CSS grows in size and complexity), you should include the .ng-enter/leave class selector in the rules with .ng-*-active:
// Instead of just:
.top.ng-enter-active {...
// You should use:
.top.ng-enter.enter-active {...
Finally, you can group identical rules together, to save space and make your code more DRY (e.g. .top.ng-enter rule === .top.ngleave.ng-leave-active rule).
Your final code should look like this:
<!-- HTML -->
<ul>
<li class="top" ng-repeat="item in items">{{item}}</li>
</ul>
/* CSS */
.top.ng-enter,
.top.ng-leave {
-webkit-transition: 1s;
transition: 1s;
}
.top.ng-enter,
.top.ng-leave.ng-leave-active {
margin-left: 100%;
}
.top.ng-enter.ng-enter-active,
.top.ng-leave {
margin-left: 0;
}
See, also, this short demo.
Just give class to your <ul> like this.
<ul class="my-anim" ng-repeat="item in items">
<li class="top">{{item}}</li>
</ul>
Working Demo
I wonder if you could help out with the code below, I understand that color styles are inherited but for some reason im not getting the expected results. For example looking at the list beginning with 'category 5' this appears blue where the subcategories e-f appear green. I have set the style as 'new_list' which should be blue is correct but this is not inheriting down the list to the other ul items in subcategory E-H.
Cheers
<style>
.new_list {color:blue;}
.all_list {color:red;}
ul {color:green;}
</style>
<ul class='all_list'>
<li>Category1
<ul class='sub_list'>
<li>SubCategoryA</li>
<li>SubCategoryB</li>
<li>SubCategoryC</li>
<li>SubCategoryD</li>
</ul>
</li>
<li>Category2</li>
<li>Category3</li>
<li>Category4</li>
</ul>
<ul class='new_list'>
<li>Category5
<ul>
<li>SubCategoryE</li>
<li>SubCategoryF</li>
<li>SubCategoryG</li>
<li>SubCategoryH</li>
</ul>
</li>
<li>Category6</li>
<li>Category7</li>
<li>Category8</li>
</ul>
you have contradicting rules applying to the same element:
you define ul:green and .new_list:blue. in the case of the main UL with class of .new_list the class rule takes precedence over the element rule since it is more specific. This is not the case when it comes to the child UL which doesn't have a .new_list class and therefore the general ul:green definition takes precedence over the default inherited color and being itself passed by inheritance to the LI children.
In other words: Inheritance is an implicit default which is overridden by any explicit rule
Brain freeze here.
What I want to do is have the Suckerfish drop down menu link to be active on the current page in the drop down as well as the top item.
I.e. below, in the Articles menu item, I'd like to have the top item "Articles" active at the same time that either Categoryone or Categorytwo is active. (Archives is a single level menu item, included here just FYI.)
I have php set up to generate a body tag with the title of the page, so the body tag for the page Categoryone is <body id="Categoryone">
HTML:
<ul class="sf-menu">
<li id="Archives-menu" class="current">Archives</li>
<li id="Articles">Articles<ul>
<li id="Categoryone-menu" class="current">Categoryone</li>
<li id="Categorytwo-menu" class="current">Categorytwo</li></ul></li>
</ul>
CSS:
#Archives #Archives-menu a, #Categoryone-menu #Categoryone-menu a, #Categorytwo-menu #Categorytwo-menu a
{
color:#fff;
}
If I throw this in #Articles #Articles-menu a to try and make Articles active, then all the links in the drop down are active.
You have not given much info about that you are truing to do. But here is my guess: Your selector is off. Try this:
#Archives a , #Archives-menu a , .current
{
color:#fff;
}
Also remove the current class from those items and add it to the appropriate item dynamically when the user is on the right page. (Maybe Sukerfish does that for you?)