简体   繁体   中英

How can I change the background color of an element using the value from an attribute in CSS on hover

I am writing a tab control where I would like each non-active tab link (menu item, not the body), to use the color assigned as an attribute on that element as the :hover background property.

Example html (dramatically simplified)

 $(document).ready(function(){ function initTabs() { var active = $('nav > ul > li.active'); if(active === undefined) { active = $('nav > ul > li:first-of-type'); } var color = active.attr('data-bgcolor'); if(color === undefined) { color = 'purple'; } $('body').css('background', color ); active.css('background', color ); } initTabs(); $('nav > ul > li:not(.active)').click(function(){ var color = $(this).attr('data-bgcolor'); if(color === undefined) { color = 'black'; } $(this).parent().find('li').each(function() { $(this).css('background', '').removeClass('active'); }) $('body').css('background', color); $(this).css('background', color).addClass('active'); }); }); 
 body { margin: 0; background: black; } nav { display: flex; flex-direction: column; background: black; } nav > ul { padding: 0; list-style-type: none; display: flex; flex: 1; margin: 0px; } nav > ul > li { padding: 5px; font-size: 1.2em; color: white; font-family: sans-serif; } /*** I have tried : background: attr(data-bgcolor); ***/ nav > ul > li:not(.active) { background: black; color: white; cursor: pointer; } nav > ul > li:not(.active):hover { background: white; color: black; } nav > ul > li.active { cursor: default; } 
 <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <nav> <ul> <li data-bgcolor="red">Home</li> <li data-bgcolor="blue">News</li> <li data-bgcolor="orange">Blog</li> </ul> </nav> 

Using the above example, I would like to set the value for

nav > ul > li:not(.active) {
  background: black;
  ...
}

Using the data-bgcolor value from the li element currently being hovered over.

I am looking for a CSS specific way to handle this (as you can see I can handle things fairly well in jQuery) because CSS just performs much faster and isn't (as) prone to quirks that occur on mouseover/mouseleave events when they happen to fast.

I have tried using the attr() value in CSS but for some reason this doesn't work for me or perhaps due to the nesting in my selectors, there is an issue there.

For the full project currently in the works, you can see my pen here

use CSS variable:

 body { margin: 0; background: yellow; } nav { display: flex; flex-direction: column; background: black; } nav > ul { padding: 0; list-style-type: none; display: flex; flex: 1; margin: 0px; } nav > ul > li { padding: 5px; font-size: 1.2em; color: white; font-family: sans-serif; } nav > ul > li:not(.active) { background: #000; color: white; cursor: pointer; } nav > ul > li:not(.active):hover { background: var(--bgcolor); color: black; } nav > ul > li.active { cursor: default; } 
 <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <nav> <ul> <li style="--bgcolor:red">Home</li> <li style="--bgcolor:blue">News</li> <li style="--bgcolor:orange">Blog</li> </ul> </nav> 

You cannot use attr the way you want:

https://developer.mozilla.org/en-US/docs/Web/CSS/attr

attr. The attr() CSS function is used to retrieve the value of an attribute of the selected element and use it in the style sheet. ... Note: The attr() function can be used with any CSS property, but support for properties other than content is experimental, and support for the type-or-unit parameter is sparse.

So

[data-bgcolor] { color: attr(data-bgcolor); }

does not work but

[data-bgcolor]::before {
  content: attr(data-bgcolor) " ";
}

does work in Chrome

I assumed you do NOT want to have

[data-bgcolor="green"] { background-color: green; }

 $(document).ready(function(){ function initTabs() { var active = $('nav > ul > li.active'); if(active === undefined) { active = $('nav > ul > li:first-of-type'); } var color = active.attr('data-bgcolor'); if(color === undefined) { color = 'purple'; } $('body').css('background', color ); active.css('background', color ); } initTabs(); $('nav > ul > li:not(.active)').click(function(){ var color = $(this).attr('data-bgcolor'); if(color === undefined) { color = 'black'; } $(this).parent().find('li').each(function() { $(this).css('background', '').removeClass('active'); }) $('body').css('background', color); $(this).css('background', color).addClass('active'); }); }); 
 body { margin: 0; background: black; } nav { display: flex; flex-direction: column; background: black; } nav > ul { padding: 0; list-style-type: none; display: flex; flex: 1; margin: 0px; } nav > ul > li { padding: 5px; font-size: 1.2em; color: white; font-family: sans-serif; } /*** I have tried : background: attr(data-bgcolor); ***/ nav > ul > li:not(.active) { background: black; color: white; cursor: pointer; } nav > ul > li:not(.active):hover { background: white; color: black; } nav > ul > li.active { cursor: default; } [data-bgcolor] { color: attr(data-bgcolor); } [data-bgcolor]::before { content: attr(data-bgcolor) " "; } 
 <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> <nav> <ul> <li data-bgcolor="red">Home</li> <li data-bgcolor="blue">News</li> <li data-bgcolor="orange">Blog</li> </ul> </nav> 

If you have a limited selection of colors you could use the attribute selector in css to overcome your current problem

[data-bgcolor="green"] { background-color: green; }
[data-bgcolor="blue"] { background-color: blue; }

If this makes sense depends on your use case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM