How can I address a dynamic list item by its content with CSS? [Not possible just with CSS] - css

I want to add a background color to a dynamic list item of the popup pane of the Thunderbird extension "Check and Send".
popup pane
The content of the first element is the sender address which changes depending on the selection when composing a message.
I found this HTML for this part of the pane in the extension's code
<!-- Identity -->
<div id="identityArea">
<h3 class="titleline-simple" l10n-tag="casPopupIdentity"></h3>
<ul>
<li class="dia_list" id="identityName"></li>
</ul>
</div>
The sender address must be added with JavaScript code which I don't understand.
I want to have different background colors depending on the content of the element.
I can easily address this element with CSS and add a fix background color
li#identityName.dia_list {
background-color: rgb(0,0,206) !important;
color: white !important;
}
but I don't know how I can have different background colors for different sender addresses.
For the elements of a different extension this works:
menuitem[label="name1 <address1#gmx.de>"],
#msgIdentity[label="name1 <address1#gmx.de>"]{
background-color: rgb(0,0,206) !important;
color: white !important;
}
menuitem[label="name2 <address2#gmx.de>"],
#msgIdentity[label="name2 <address2#gmx.de>"]{
background-color: rgb(255,255,0) !important;
}
...
but this does not work for the list element. I also tried value and content instead of label but neither works.
Is there a way to address the list element by its content?

According to the comment of mrmonsieur it is not possible just with CSS.
What is happening in the different extension is that the label attribute is set and that is used in the css with the attribute selector (code in square brackets). If there is any attribute being set containing the address information, you can do something similar, otherwise you have to learn some JavaScript. In particular the .innerHTML property would be handy here.
JavaScript is needed to address the content of the item.

Related

Tab accessibility within a hover state

I have a component that, upon a hover, shows a button and a link that you can click on. This is not a menu... just a box in the middle of the page.
For accessibility, I would like a user to be able to tab into the container (happens now, and displays the content in the .HiddenUntilHover class) AND also continue to tab to the button and link that show up on the hover/focused state.
Right now you can focus on the container and see the hover state; however, when you tab it just goes to the next element and does not allow you to tab to the button or link WITHIN the hover state.
Pseudo code example:
/* My component .jsx */
<div tabIndex="0" className="MainContainer">
<div className="SomeOtherClass">
<div className="HiddenUntilHover">
/* I would like to be able to tab to these clickable things! */
<button>Click me!</button>
I am also clickable
</div>
</div>
</div>
And my SCSS:
.HiddenUntilHover {
display: none;
}
MainContainer:focus,
MainContainer:hover,
> .HiddenUntilHover {
display: block
}
I ran into this issue a few days ago and I solved it using css classes to make the hovered content accessible via keyboard navigation.
The way I got this working was to use css pseudo-classes to ensure that when the div element is active & focused that the buttons inside also display. Specifically the additional use of :focus-within & :focus-visible should ensure that when you tab over the list items, their contents are also displayed and keyboard accessible.
.MainContainer {
&:not(:hover, :focus, :active, :focus-visible, :focus-within) {
.HiddenUntilHover {
visibility: hidden;
}
}
}
<body>
<div tabIndex="0" className="MainContainer">
Content
<div className="SomeOtherClass">
<div className="HiddenUntilHover">
<button>Click me!</button>
I am also clickable
</div>
</div>
</div>
</body>
Here's a link to the Codesandbox demo of this working
When the box is in focus, tabbing further to the button will make the box blur, which will hide it, and its contents, so focus will move to the next accessible element. I think this is the behavior you are experiencing.
You might consider using inserting an aria-activedescendant or tabindex attribute when the box comes into focus. This requires a little javascript.
Strictly speaking, you don't need to rely on the hover state to make that control accessible. You could have an offscreen (or clipped) button/link that is not a DOM child of the hidden (display:none) box. If you take this approach, read up on the aria-owns attribute.
As long as it is marked up as a button or link (or has a tabindex="0" setting), and is not 'really' hidden, it ought to be possible to tab to it.
Try increasing the properties of the class MainContainer
for example.
.MainContainer {
width: 100%;
height: 100px;
}
.MainContainer .HiddenUntilHover {
display: none;
}
.MainContainer:hover .HiddenUntilHover, .MainContainer:focus .HiddenUntilHover {
display: block;
}
Elements appearing on hover are inherently inaccessible. You are experiencing one side of the problem with your code, where it is difficult to make it keyboard accessible.
But think about touch screens that have no real concept of hover: is there some way to reach your button on a smarphone or tablet?
For a more pragmatic answer, if you need to stay with hover, a less hacky solution than the two already posted ones could be the following:
use focusin and focusout events. See for example this question for explanations and differences with focus/blur, and this w3school doc for browser compatibility.
You will have to structure your HTML differently, such as:
<div id="outer">
<div id="hover">
...
</div><!--hover-->
<button>Your button which only appears on hover</utton>
</div><!--outer-->
As well as use a bit of js:
$('#outer').on('focusin', __=>$('#hover').classNames.add('keep-visible'));
$('#outer').on('focusout', __=>$('#hover').classNames.remove('keep-visible'));
With a corresponding .keep-visible class which will leave the element display:block (I'm not a CSS expert, I let you write the code).
The overal functionning is the following: when some element within #outer takes the focus, the focusin element is fired due to bubbling. In the event, you put your class .keep-visible which makes the element to stay visible.
The focusout event is fired when the focus leaves the last element within #outer. At that point you remove the .keep-visible class, which makes the element to disappear.
According to the link above, onfocusin/out aren't standard, but are supported by all major browsers including IE. Firefox is the last one to implement it in 52.0, so it's a kind of defacto standard; we can reasonably expect that it won't disappear soon.

Trying to set style of div using ng-repeat

I am trying to change the background color of a div using ng-repeat. The color I am trying to pull from the object in the loop. Whenever I do this however it sets my style property equal to blank.
Here is the code that I am using:
<div ng-repeat="channel in channelObjects">
<div class="mediumTile" style="background-color:#{{channel.Color}}">
Channel Color: {{channel.color}}
</div>
</div>
This displays my mediumTile object with the correct channel color displayed. By the style is set to nothing once the page loads
This is what the page displays:
<div class="mediumTile" style="">
Channel Color: 123456
</div>
Am I doing something wrong?
You should use ng-style instead of style, using style with interpolation will cause some browsers to strip the values off (invalid style attribute with the presence of {{ etc..) before even angular has a chance to process it. This happens specifically in IE (not sure which browser you tested this).
<div class="mediumTile" ng-style="{'background-color':'#' + channel.color}">
Also mind the casing as well, color.
Plnkr

CSS - Set Content of Second Element Using ~ to Title of First

I am attempting to create a tooltip system using CSS and a very small amount of JavaScript. So far I have created a structure that goes as follows:
<div class="tooltip" title="foo"></div>
<div class="tooltip" title="bar"></div>
<span id="tooltip-span"></span>
I have created several CSS styles so that the tooltip span is shown on hover and a little bit of JavaScript moves the tooltip to the correct location depending on the mouse position.
However, I have had trouble attempting to make the tooltip's content correspond to the div being hovered over. I have tried using the following CSS, but to no avail:
.tooltip:hover ~ #tooltip-span {
display: inline;
content: attr(title);
}
Is there any way to make the span element have the content of the title of the div being hovered over using CSS?
Thanks for reading!
With pure CSS, no. content: attr(title) sets the content to the title attribute of the matched element, which in your case is #tooltip-span.
To have that work in the way you want, you'd need to update the title attribute of <span id="tooltip-span"></span> using Javascript.

Why wouldn't this CSS ID and Class style superceed the Class style alone?

Here is a typical Drupal Cascade for a superfish menu (note the ID in the first line and the class in the last) :
<ul id="superfish-3" class="menu sf-menu sf-menu-materials sf-vertical sf-style-MatMenu2 sf-total-items-23 sf-parent-items-22 sf-single-items-1 superfish-processed sf-js-enabled sf-shadow">
<li id="menu-899-3" class="first odd sf-item-1 sf-depth-1 sf-no-children">
<li id="menu-900-3" class="middle even sf-item-2 sf-depth-1 sf-total-children-8 sf-parent-children-0 sf-single-children-8 menuparent">
<a class="sf-depth-1 menuparent sf-with-ul" title="FRUIT" href="/specs/03">
FRUIT
<span class="sf-sub-indicator"> ยป</span>
</a>
There is a default menu arrow image defined in the css:
.sf-sub-indicator {
background-image: url('../images/arrows-black.png');
}
and I want to change the file from a black arrow to a red one and have created the appropriate .png file. Its css is:
#superfish-3 .sf-sub-indicator {
background-image: url('../images/arrows-red.png');
}
When I display the page, the arrows are not changed and firebug tells me that the original style is used. I thought an ID scores higher than a class. How do I express the selector to have it supersede the generic black one?
ADDED CONTENT:
I have several other styling features such as a border that also fail if I add an ID. I know that borders don't pass on in inheritance, but inheritance is moving from the .sf-sub-indicator to #superfish-3 .sf-sub-indicator, so I would assume my red arrows would show, but the don't. This is specifically related to adding the ID, but only for certain style settings. For instance my link color is green and I change it to red for this ID. That works fine.
ADDED MORE:
I created a class at the <li> level and it works. There is something about having the ID or something about the classes that come between the ID and the link (?).
Just go up the tree one level:
a .sf-sub-indicator {...
Stop guessing at it. Any browser's dev tools will be able to tell you what styles are in effect and what styles are being overridden. IE's "Trace Styles" tab is particularly useful for this task:
Select the element in question and expand the appropriate CSS attribute. You'll see each matching selector that defines that style. Then, make your selector stronger than the strongest selector.
yeah the html/css looks sound. weird.
well, you could always just do:
#superfish-3 .sf-sub-indicator {
background-image: url('../images/arrows-red.png') !important;
}
if you don't mind a little hackery.

What does a[href^="..."] do in CSS?

I have used CSS before and I came across the below CSS style, don't have a clue what it does.
a[href^="http:"] {
background: url(img/keys.gif) no-repeat right top;
}
a[href^="http://mysite.com"], a[href^="http://www.mysite.com"] {
background-image: none; padding-right:0;
}
a[href^="http:"]
Selects an <a> element whose href attribute value begins with http:.
For example:
p[title^="para"] {background: green;}
Will match the following:
<p title="paragraph"> This paragraph should have a green background. </p>
That's one of the substring-matching attribute selectors available in CSS3. It matches links with href attributes whose values start with the given string.
To illustrate, we'll take your example CSS, and add some defaults:
a {
background: none; padding: 0 1em;
}
a[href^="http:"] {
background: url(img/keys.gif) no-repeat right top;
}
a[href^="http://mysite.com"], a[href^="http://www.mysite.com"] {
background-image: none; padding-right:0;
}
And style the following HTML with it. The output styles are summarized in comments:
<ul>
<!-- [1] No background, 1em left and right padding -->
<li>My site's page</li>
<!-- [2] Background, 1em left and right padding -->
<li>External link</li>
<!-- [3] No background, no right padding -->
<li>My site's base URL without www</li>
<!-- [4] No background, no right padding -->
<li>My site's base URL with www</li>
<!-- [5] No background, no right padding -->
<li>A page in my site with base URL</li>
</ul>
What's happening?
Selected by a only
This element's href="/index.php" attribute doesn't start with http: or the other values.
There is no background, but there is left and right padding.
Selected by a[href^="http:"] only
This element's href="http://example.com" attribute starts with http: but doesn't start with http://mysite.com.
There is both left and right padding, and a background image.
Selected by a[href^="http:"] and a[href^="http://mysite.com"]
This element's href="http://mysite.com" attribute starts with http: and further starts with http://mysite.com.
Since the second selector overrules the first selector, the background image and right padding are removed.
Selected by a[href^="http:"] and a[href^="http://www.mysite.com"]
This element's href="http://www.mysite.com" attribute starts with http: and further starts with http://www.mysite.com (notice the www).
Since the second selector overrules the first selector, the background image and right padding are removed.
Selected by a[href^="http:"] and a[href^="http://mysite.com"]
This element's href="http://mysite.com/page.php" attribute starts with http: and further starts with http://mysite.com.
Notice that, compared to the third link, the attribute in this one contains more than just the base URL; however, the ^= indicates that the attribute's value just needs to start with your site's base URL, as opposed to = which would mean "select links that only point to http://mysite.com". Therefore, this link is matched by the second selector.
Since the second selector overrules the first selector, the background image and right padding are removed.
Those are attribute-starts-with selectors, they'll select <a> elements with an href attribute starting with that value, e.g. a[href^="http:"] matches any anchors with an href starting with href="http:....", for example:
Test <!-- would match -->
Test <!-- wouldn't match -->
For every link which's "href" parameter starts with "http:", set the background to a key image (without repetition, positioned in the top-right corner).
For every link which's "href" parameter starts with "http://mysite.com" or "http://www.mysite.com", set the background image to nothing (and the right-side padding to 0).
To me, this seems like a clever CSS trick that will make your users aware of when they are leaving your website through an external link by displaying a key image.
(I think I'll use it in the future. :)
The rules say, according to the W3C docs:
All anchors which have an href attribute that starts with http:
All anchors which have an href attribute that start with http://mysite.com or http://www.mysite.com
It's an attribute selector.
The ^= part means that the href attribute of the anchor tags must begin with http: in your first example.

Resources