CSS Sibling's Children Selector - css

I have the following structure that I've simplified down, the goal here was to set the span with the class "partA" background color to pink because the input has the class "state".
The internal structure of the "container" cannot change.
So the end result for this example would be the first "Content" label would be highlighted pink.
Note that there can be any number of "container"s in any order throughout the page structure, so just selecting the first container isn't a suitable solution.
<span class="container">
<span class="item">
<span class="partA">Content</span>
<span class="partB">A</span>
</span>
<input class="element state" />
</span>
<span class="container">
<span class="item">
<span class="partA">Content</span>
<span class="partB">B</span>
</span>
<input class="element" />
</span>
I thought the general sibling selector may be the solution, but it doesn't seem to work - I believe because it's a sibling of the parent, not the element itself. I tried both ways round in case I had made a mistake:
.partA ~ .state { background-color: pink; }
.state ~ .partA { background-color: pink; }
I've created a JSFiddle with this structure.
Can anyone provide me a selector which will accomplish this? I would like to avoid JS if at all possible.

CSS renders always in a forward sequence. So, what you want could only work if the input came first in the structure:
.state ~ span .partA { background-color: pink; }
<span class="container">
<input class="element state" />
<span class="item">
<span class="partA">Content</span>
<span class="partB">A</span>
</span>
</span>
<span class="container">
<input class="element" />
<span class="item">
<span class="partA">Content</span>
<span class="partB">B</span>
</span>
</span>

As per this CSS Tricks article
"there are no parent selectors in CSS, not even in CSS3"
The article is worth a read, but I suspect the only way you are going to be able to do this is with javascript.

I'll offer a sort-of-solution that might work for you.
HTML
<span class="container">
<input class="element state" />
<span class="item">
<span class="partA">Content</span>
<span class="partB">A</span>
</span>
CSS
.state ~ .item .partA { background-color: pink; }
This way you swap the DOM elements around, which you than could position with CSS.
See the fiddle here: http://jsfiddle.net/edkyy360/4/

Since it's not possible to back-track selectors using pure CSS
let's find a solution adding the minimal effort:
Place this before the closing </body> tag:
<script>
// Add PINK background to the first `.partA` element whose uncle has `.state`
var stateClass = document.getElementsByClassName("state");
for(var i=0; i<stateClass.length; i++){
stateClass[i].parentElement.getElementsByClassName("partA")[0].style.background = "pink";
}
</script>
var stateClass = document.getElementsByClassName("state");
for(var i=0; i<stateClass.length; i++){
stateClass[i].parentElement.getElementsByClassName("partA")[0].style.background = "pink"
}
<span class="container">
<span class="item">
<span class="partA">Content</span>
<span class="partB">A</span>
</span>
<input class="element state" />
</span>
<span class="container">
<span class="item">
<span class="partA">Content</span>
<span class="partB">B</span>
</span>
<input class="element" />
</span>

Related

Exclude tag from style if with tag falls below other tag/class name

I want to only style a tag if it does not exists under a specific tag.
I want one css selector to be able to handle scenario1 and scenario2 as per the sample below. The selector should colour the tag "bdi" with the text 1300 and 1400 but exclude "bdi" tag with text 1500 because that "bdi" tag is a child of the "del" tag.
I was hoping the :not selector could help but I can't seem to get it working.
Thank you
.price .amount bdi {
color:red;
}
<div>
<div class="scenario1">
<p class="price">
<span class="amount">
<bdi>1300</bdi>
</span>
</p>
</div>
<div class="scenario2">
<p class="price">
<del>
<span class="amount">
<bdi>1500</bdi>
</span>
</del>
<ins>
<span class="amount">
<bdi>1400</bdi>
</span>
</ins>
</p>
</div>
<div>
Try like this:
.price > .amount > bdi,
.price > ins > .amount > bdi {
color:red;
}
<div>
<div class="scenario1">
<p class="price">
<span class="amount">
<bdi>1300</bdi>
</span>
</p>
</div>
<div class="scenario2">
<p class="price">
<del>
<span class="amount">
<bdi>1500</bdi>
</span>
</del>
<ins>
<span class="amount">
<bdi>1400</bdi>
</span>
</ins>
</p>
</div>
<div>
By specifying that .amount must be the direct descendant of .price, you rule out the possibility of there being a del element 'between' the two. Similarly, you can specify an ins element between them in a selector.

Css bug with Navbar

I'am having an strange issue with a switch whenever it is inside my webs navbar, I`ve made a fiddle to replicate the issue:
Issue replication
<header>
<div class="navbar-fixed">
<nav style="background: #F30617" role="navigation">
<div class="nav-wrapper">
<a id="logo-container" href="#Url.Action(" Main ", "Home ")" class="brand-logo">
<div class="flow-text title" style="white-space: nowrap;">Planning Cycle Dashboard</div>
</a>
<div class="switch" style="float: right">
<label>
<input type="checkbox" class="upsellActiveToggle" checked="checked"><span class="lever">
<span class="off center-align" style="color: white;">Today</span>
<span class="on center-align" style="color: white;">Weekend</span>
</span>
</label>
</div>
</div>
</nav>
</div>
</header>
<main>
<div class="switch">
<label>
<input type="checkbox" class="upsellActiveToggle" checked="checked"><span class="lever">
<span class="off">Today</span>
<span class="on">Weekend</span>
</span>
</label>
</div>
</main>
And as you can see, what I want to achieve is the switch that is below the navbar.
My question is...why if it is working on the switch below the navbar it does not on the one that is inside the navbar? It has the same structure...it should work!
Dont know why it pushes the text outside the switch!
Any ideas?
First of all, you have a typo in your html:
<span class="off center-align" style="color: white;">Today</span>
<span class="on center-align" style="color: white;"></span>
Weekend
</span>
See Weekend is out of the .on span? You would not miss it if you had made your code indented better.
Fix it first, then add:
.switch label .lever, .switch label .lever span {line-height:20px}
it will do the trick as without it they inherit line-height:56px from nav.

Calling a directive on another element on click

I'm currently trying to apply a background-color to the p elements within the 1st div by checking a checkbox that's located within the 2nd div. I'm calling a directive when the input box is clicked, "text-theme-switch", to manipulate the p elements in the first div
<!--HTML-->
<div id="#div1" class="text-main-window">
<div class="text-view-div">
<div ng-repeat="item in text.obj">
<h3 id="{{item.id}}-title">{{item.title}}</h3>
<br/>
<div ng-repeat="art in item.article">
<h4 id="{{art.id}}-art">{{art.artNum}}</h4>
<br/>
<div ng-repeat="subArt in art.subArt " >
<h5 id="{{subArt.id}}-subart" >{{subArt.subArtNum}}</h5>
<div ng-repeat="para in subArt.paragraph" >
<p class="theme-para {{para.ruleTheme}} text-item">{{para.text}}</p>
</div>
<a ui-sref="rulebook.rules.detail({detail:rules.ruleNumber})"
class="rule-style"
ng-repeat="rules in subArt.rule">
{{rules.ruleNumber}} {{rules.ruleName}}<br/>
</a>
<br/>
</div>
</div>
</div>
</div>
</div>
<div class="theme-filter-text-theme">
<h4>Text Themes</h4>
<div class="onoffswitch pull-right">
<input text-theme-switch
ng-model="text.themeView"
val="text.themeView"
ng-change="text.test()"
type="checkbox"
name="onoffswitch"
class="onoffswitch-checkbox"
id="myonoffswitch"
ng-click="showLegend = !showLegend">
<label class="onoffswitch-label" for="myonoffswitch">
<span class="onoffswitch-inner"></span>
<span class="onoffswitch-switch"></span>
</label>
</div>
<div class="styles-hr"></div>
<div ng-show="showLegend" class="theme-filter-item" ng-repeat="item in text.themes">
<span class="theme-check-tag"
ng-class="{
checkgreen: item.theme === 'enforcement', checkpink: item.theme === 'customer due diligence',
checkorange: item.theme === 'record keeping',
checkblue: item.theme === 'reporting'
}" >
{{item.theme}}
</span>
</div>
</div>
This is the directive that is manipulating the DOM elements in the first div.
//DIRECTIVE
(function(){
'use strict';
angular.module('ganeshaApp')
.directive('textThemeSwitch', function(){
return{
restrict: 'A',
transclude: true,
scope: {textTheme: "="},
link: function(scope, element, attrs){
element.on('click', function(){
$('.text-main-window h3').toggleClass('grey-on');
$('.text-main-window h4').toggleClass('grey-on');
$('.text-main-window h5').toggleClass('grey-on');
$('.rule-style').toggleClass('grey-on');
$('.text-main-window p:not(.rk-class, .enforcement-class, .cdd-class, .reporting-class)').toggleClass('grey-on')
$('.rk-class').toggleClass('rk-class-active');
$('.cdd-class').toggleClass('cdd-class-active');
$('.enforcement-class').toggleClass('enforcement-class-active');
$('.reporting-class').toggleClass('reporting-class-active');
})
}
};
});
})();
And here's the CSS
/*CSS*/
.cdd-class-active{
background-color: $themePink;
#include borderRadius;
}
.reporting-class-active{
background-color: $themeBlue;
#include borderRadius;
}
.rk-class-active{
background-color: $themeOrange;
#include borderRadius;
}
.enforcement-class-active{
background-color: $themeGreen;
#include borderRadius;
}
.highlight-on{
background-color: $veryPaleYellow
}
.grey-on{
opacity: .5;
background-color: white;
}
While the above code is working, I feel like I'm using a whole lot of bad practices here. From what I've read, DOM manipulation should be done from directives. I've also read that in Angular scope should be used rather than selectors, but I can't figure out how a directive should be used with a click event to manipulate the DOM of other elements rather than the one clicked. Should this type of work be delegated to the controller and should the directive be called from somewhere else, or can anyone recommend a cleaner way to do this, using scope rather the selectors?
So I figured out where I was going wrong here. I was putting the directive on the checkbox input and trying to work off the click event. Because of this, I had to search through and find all the elements that needed to be manipulated. What I should have been doing was putting the directives on the elements that needed to be manipulated as seen below.
<div id="#div1" class="text-main-window">
<div class="text-view-div">
<div ng-repeat="item in text.obj">
<h3 class="grey" text-theme-grey="text.themeView" id="{{item.id}}-title">{{item.title}}</h3>
<br/>
<div ng-repeat="art in item.article">
<h4 class="grey" text-theme-grey="text.themeView" id="{{art.id}}-art">{{art.artNum}}</h4>
<br/>
<div ng-repeat="subArt in art.subArt " >
<h5 class="grey" text-theme-grey="text.themeView" id="{{subArt.id}}-subart">
{{subArt.subArtNum}}
</h5>
<div ng-repeat="para in subArt.paragraph" >
<p text-theme-color='text.themeView' class="theme-para {{para.ruleTheme}} text-item">{{para.text}}</p>
</div>
<a ui-sref="rulebook.rules.detail({detail:rules.ruleNumber})"
class="rule-style grey"
text-theme-grey="text.themeView"
ng-repeat="rules in subArt.rule">
{{rules.ruleNumber}} {{rules.ruleName}}<br/>
</a>
<br/>
</div>
</div>
</div>
</div>
<div class="theme-filter-text-theme">
<h4>Text Themes</h4>
<div class="onoffswitch pull-right">
<input ng-model="text.themeView"
type="checkbox"
name="onoffswitch"
class="onoffswitch-checkbox"
id="myonoffswitch"
ng-click="showLegend = !showLegend">
<label class="onoffswitch-label" for="myonoffswitch">
<span class="onoffswitch-inner"></span>
<span class="onoffswitch-switch"></span>
</label>
</div>
<div class="styles-hr"></div>
<div ng-show="showLegend" class="theme-filter-item" ng-repeat="item in text.themes">
<span class="theme-check-tag"
ng-class="{
checkgreen: item.theme === 'enforcement', checkpink: item.theme === 'customer due diligence',
checkorange: item.theme === 'record keeping',
checkblue: item.theme === 'reporting'
}" >
{{item.theme}}
</span>
</div>
</div>
Now the directives watch the value of the model on the switch for for changes and the classes are added or removed for each element accordingly.
(function(){
'use strict';
angular.module('ganeshaApp')
.directive('textThemeGrey', function(){
return{
restrict: 'A',
link: function(scope, element, attrs){
scope.$watch(attrs.textThemeGrey, function(newVal){
if(newVal){
element.addClass('on')
}else{
element.removeClass('on')
}
})
}
}
})
})();
A much cleaner solution, I think. Hope this helps someone.

Editing the Reddit Enhancement Suite's Userbar

I'm currently trying to edit the RES userbar for my subreddit. It looks like this:
It also collapses.
I want to float almost all of the elements to the right so that they are lined up vertically. The html for the bar is:
<div id="header-bottom-right" class="res-navTop">
<div id="userbarToggle" title="Toggle Userbar" class="userbarHide">»</div>
<span class="user">
<a href="http://www.reddit.com/user/snowe2010/" style="margin-right: 2px;">
snowe2010
</a>
<span id="RESAccountSwitcherIcon"></span>
(
<span class="userkarma" title="">
<a title="link karma" href="/user/snowe2010/submitted/">9</a>
·
<a title="comment karma" href="/user/snowe2010/comments/">
2170
</a>
</span>
)
</span>
<span class="separator">|</span>
<a title="no new mail" href="http://www.reddit.com/message/inbox/" class="nohavemail" id="mail"></a>
<a id="mailCount" href="/message/unread/"></a>
<span class="separator">|</span>
<a title="no new mod mail" href="http://www.reddit.com/message/moderator/" class="nohavemail" id="modmail">mod messages</a>
<span class="separator">|</span>
<ul class="flat-list hover">
<li>
preferences</li>
</ul>
<span class="separator">|</span>
<span id="openRESPrefs">
<span id="RESSettingsButton" title="RES Settings" class="gearIcon newNotification">
</span>
</span>
<span class="separator">|</span>
<form method="post" action="/logout" class="logout hover">
<input type="hidden" name="uh" value="zoimwqbhhl59526448277e691374c3d0bc47706bb35d0045b9">
<input type="hidden" name="top" value="off">
logout
</form>
</div>
I've currently tried setting each element to a block and then floating right, but that isn't working. I've also tried setting them to display: table-cell; and aligning it, but that isn't working either.
Can anybody help me with this?
#header-bottom-right a {
display: block;
float: right;
}
#header-bottom-right .separator { display: none; }
This is a pretty unrefined approach, but it's a starter. There's plenty of room for smoothing out the rough edges if you want to continue with this approach.

Css selectors SharePoint 2010

I have the following html structure:
<div class="ms-PostFooter">
<span style="">
<span style="" class="s4-clust">
<a href="#" style="">
<img src="" alt="" style="l" title="" class="imglink" longDesc="" />
</a>
</span>
</span>
<span style="">
<span class="s4-clust">
<a href="#" style="">
<img src="" alt="" style="" title="" class="imglink" longDesc="" />
</a>
</span>
</span>
<span style="">
<span class="s4-clust">
<a href="#" style="">
<img src="" alt="" style="" title="Number of Comments" class="imglink" longDesc="" />
</a>
</span>
</span>
</div>
In css how would I select the third tag in order to hide the image with title "Number of Comments"?
.ms-PostFooter span::nth-child(3) img {
display: none;
}
or this also works:
img[title="Number of Comments"] {
display: none;
}
however these rely on your markup / content. the best way would be - generate a specific class on that image or its container, server-side (if you can)
One possibility if your title is unique:
[title="Number of Comments"]
{
display:none;
}
You can use the following:
div :last-child span .imglink{
display:none;
}
jsfiddle: http://jsfiddle.net/kGThS/1/
This may be more specific:
.ms-PostFooter :last-child span .imglink{
display:none;
}
jsfiddle: http://jsfiddle.net/kGThS/3/
To hide the entire last span/link as per your comment below use the following:
.ms-PostFooter :last-child span{
display:none;
}
Somehow through css sharepoint was not allowing me to use any of the selectors mentioned here through css to get rid of the specif tag containing the link and image to be removed so I decided to use jquery instead which did the trick as follows:
$( document ).ready(function() {
$('DIV.ms-PostFooter span:nth-child(3)').css('display', 'none');
$('DIV.ms-PostFooter span:nth-child(4)').css('display', 'none');
});
Thanks for all the assistance.

Resources