Sass select parent if child has a specific class - css

Is there any sort of way to select a parent element in sass if the child contains a certain class?
Basically I am using the tooltipster plugin and have this issue
HTML
<div class="tooltipster-content">
<span id="note-options">
<ul>
<li>Create new note</li>
<li>Add new edit note</li>
</ul>
</span>
</div>
CSS
#note-options {
//From here, select the .tooltipster-content parent
ul {
li {
}
}
}
I need to be able to select the .tooltipster-content class based on the id of the span tag.
Tooltipster will always generate with the same HTML structure, but I dont want to change the tooltipster wrapper for all tooltips, I want to do it per each tooltip.
As tooltipster doesn't add your specified id to the parent wrapper for basic CSS editing, the only way I can think of is trying to use the span ID to select the closest .tooltipster-content class.
Is this achievable?
Note - I do not want to use javascript/jquery to fix this, I want to try and achieve it in CSS/SASS.

Nope. There's no way in CSS or any preprocessor that you can travel up the dom to select a parent. JS is the only way.
If you have jQuery, you can simply use .parent().

Related

CSS: is there a way to insert the content of an attribute as text in my output?

Normally, CSS works by matching element names in the HTML:p.heading1 {} affects all elements of type p with class heading1.
Is there a way to display an object/text that only exists as an attribute?
For example, this is my HTML:
<body var="text I want to insert">
<div class="titlepage">
<p class="titlepagetext">this should also be displayed</p>
The title page has a number of <p> children. In addition to them, I want to display the content of body/var on the title page.
You can probably consider CSS variables. The custom property will get inherited by all the elements inside the body and you can use pseudo element to display it where you want:
.titlepage:before {
content:var(--var);
}
<body style="--var:'text I want to insert'">
<div class="titlepage">
<p class="titlepagetext">this should also be displayed</p>
</div>
</body>
AH Formatter has an -ah-attr-from() extension function that will let you get the contents of an ancestor's attribute (see https://www.antennahouse.com/product/ahf66/ahf-ext.html#attr-from).
You could use -ah-attr-from() in a rule for .titlepagetext::before.
When you using css, you can't target parent. There is no way to get parent selector. And content: "" can apply only for pseudo-classes.

ASP.Net Core MVC asp-validation-summary styling

How do I get rid of the bullets for each model error. Is there a style property? I don't see one in intellisence.
The validation summary helper will render each error message as a list item inside a ul. You can always customize it using your own CSS.
<form asp-action="Index">
<div asp-validation-summary="All" id="myCustomSummary"></div>
<!-- your form elements goes here-->
<button id="btnadd">Save</button>
</form>
Here, I gave an Id attribute to the div so that I can selectively override the ul list items inside that div.
To remove the bullet from each list item, you can set the list-style-type to none in your stylesheet:
#myCustomSummary ul li {
list-style-type: none;
}
The nice thing about the Tag Helpers is that they pass all non-ASP attributes directly to the rendered HTML tag without any processing. So normally, you can simply add the class list-unstyled to the class attribute if you're using Bootstrap, or add the relevant CSS to the style attribute if you're not using Bootstrap. No custom ASP attributes are required.
However, the problem with the validation summary Tag Helper is that it renders the <ul> tag inside a <div> tag, so your class or style will be applied to the <div> which is not very useful. I don't know the reason behind their decision to create the validation summary Tag Helper on a seemingly useless <div> tag instead of directly on the <ul> tag, which would've been much easier to directly style and manipulate as I mentioned above (which is the case for all other tag helpers), but having it done this way leaves us no choice but using CSS in <style> tags or style sheets.
The other answer by Shyju is fine if you want to target a specific validation summary. However, you most likely want to target all validation summaries in the same way, in which case you're better of using a class instead of ID.
If you view the source code, you will notice that the validation summary renders HTML similar to this:
<div class="validation-summary-errors">
<ul>
<li>The First Name field is required.</li>
<li>The Last Name field is required.</li>
<li>The Date Of Birth field is required.</li>
</ul>
</div>
So you can simply target the validation-summary-errors class like this:
.validation-summary-errors ul {
padding-left: 0;
list-style: none;
}
This code is a copy of the Bootstrap class list-unstyled, which completely removes all list styling. If you prefer to keep the padding, then delete the first line.
Now, if you want to target all validation summaries on a specific page, then add the above CSS to that page, and if you want to target all validation summaries on all page of your website, then add the above CSS to you website's style sheet.

Display a class using :after

I have a simple problem here. What I need to do is that I need to place a class after span in a button. Like if:
<button class="test-button">
<span>This is button</span>
</button>
<span class="custom"> I need to place this after Test button using :after </span>
So if its not clear, I need to place the custom class after the span of text-button class. I was trying to accomplish this by using
.test-button span:after {
content:attr([class=".custom"]);
}
but its not working ...
content:attr doesn't work quite like that; it fetches the value of an attribute, rather than setting one (see example). I believe you can't set an attribute in that way - you'll have to apply the individual properties of .custom in the :after declaration manually.

css way to make appear list elements <li/> with certain class on top of list

Is there any css way to bubble up <li> elements with some class on top of list. I guess I have come across some way to do this in the past but cant remember how to do this exactly.
Please note I dont need to rearrange in markup. Just make the elements with certain class appear as if on top of other elements without that class.
Can anyone tell if there is some way to do this?
With pure CSS, you can move an element to the top of the list using absolute positioning, though it would not actually be at the top of the list as far as the markup is concerned. What you want to do can be achieved with javascript however. Using jQuery, you would want to do something along these lines:
HTML:
<ul id="myList">
<li>Second</li>
<li>Third</li>
<li>Fourth</li>
<li class="top">First</li>
<li>Fifth</li>
</ul>
Javascript:
$(document).ready(function () {
var list = $('#myList');
list.children('li.top').remove().prependTo(list);
});
Working example: http://jsfiddle.net/tMWJs/
Edit:
To do this with pure CSS, use absolute positioning. Here is an example of the css you would need:
ul#myList {position:relative; margin-top:40px;}
ul#myList li {line-height:20px;}
li.top {position:absolute; top:-20px;}
If you have multiple elements to move, this approach would need tinkering to position each element seperately, and is probably not suitable.
Working example: http://jsfiddle.net/sp73f/

Complex CSS selector for parent of active child [duplicate]

This question already has answers here:
Is there a CSS parent selector?
(33 answers)
Closed 9 years ago.
Is there a way to select a parent element based on the class of a child element in the class? The example that is relevant to me relating to HTML output by a nice menu plugin for http://drupal.org. The output renders like this:
<ul class="menu">
<li>
<a class="active">Active Page</a>
</li>
<li>
<a>Some Other Page</a>
</li>
</ul>
My question is whether or not it is possible to apply a style to the list item that contains the anchor with the active class on it. Obviously, I'd prefer that the list item be marked as active, but I don't have control of the code that gets produced. I could perform this sort of thing using javascript (JQuery springs to mind), but I was wondering if there is a way to do this using CSS selectors.
Just to be clear, I want to apply a style to the list item, not the anchor.
According to Wikipedia:
Selectors are unable to ascend
CSS offers no way to select a parent or ancestor of element that satisfies certain criteria. A more advanced selector scheme (such as XPath) would enable more sophisticated stylesheets. However, the major reasons for the CSS Working Group rejecting proposals for parent selectors are related to browser performance and incremental rendering issues.
And for anyone searching SO in future, this might also be referred to as an ancestor selector.
Update:
The Selectors Level 4 Spec allows you to select which part of the select is the subject:
The subject of the selector can be explicitly identified by prepending
a dollar sign ($) to one of the compound selectors in a selector.
Although the element structure that the selector represents is the
same with or without the dollar sign, indicating the subject in this
way can change which compound selector represents the subject in that
structure.
Example 1:
For example, the following selector represents a list item LI unique child of
an ordered list OL:
OL > LI:only-child
However the following one represents an ordered list OL having a unique child,
that child being a LI:
$OL > LI:only-child
The structures represented by these two selectors are the same,
but the subjects of the selectors are not.
Although this isn't available (currently, November 2011) in any browser or as a selector in jQuery.
You can use has():
li:has(a:active) {
/* ... */
}
Unfortunately, there's no way to do that with CSS.
It's not very difficult with JavaScript though:
// JavaScript code:
document.getElementsByClassName("active")[0].parentNode;
// jQuery code:
$('.active').parent().get(0); // This would be the <a>'s parent <li>.
Late to the party again but for what it's worth it is possible using jQuery to be a little more succinct. In my case I needed to find the <ul> parent tag for a <span> tag contained in the child <li>. jQuery has the :has selector so it's possible to identify a parent by the children it contains (updated per #Afrowave's comment ref: https://api.jquery.com/has-selector/):
$("ul").has("#someId")
will select the ul element that has a child element with id someId. Or to answer the original question, something like the following should do the trick (untested):
$("li").has(".active")
THE “PARENT” SELECTOR
Right now, there is no option to select the parent of an element in CSS (not even CSS3). But with CSS4, the most important news in the current W3C draft is the support for the parent selector.
$ul li:hover{
background: #fff;
}
Using the above, when hovering an list element, the whole unordered list will be highlighted by adding a white background to it.
Official documentation: https://www.w3.org/TR/2011/WD-selectors4-20110929/#overview (last row).
The first draft of Selectors Level 4 outlines a way to explicitly set the subject of a selector. This would allow the OP to style the list element with the selector $li > a.active
From Determining the Subject of a Selector:
For example, the following selector represents a list item LI unique child of an ordered list OL:
OL > LI:only-child
However the following one represents an ordered list OL having a unique child, that child being a LI:
$OL > LI:only-child
The structures represented by these two selectors are the same, but the subjects of the selectors are not.
Edit: Given how "drafty" a draft spec can be, it's best to keep tabs on this by checking the CSSWG's page on selectors level 4.
Future answer with CSS4 selectors
New CSS Specs contain an experimental :has pseudo selector that might be able to do this thing.
li:has(a:active) {
/* ... */
}
The browser support on this is basically non-existent at this time, but it is in consideration on the official specs.
Answer in 2012 that was wrong in 2012 and is even more wrong in 2018
While it is true that CSS cannot ASCEND, it is incorrect that you cannot grab the parent element of another element. Let me reiterate:
Using your HTML example code, you are able to grab the li without specifying li
ul * a {
property:value;
}
In this example, the ul is the parent of some element and that element is the parent of anchor. The downside of using this method is that if there is a ul with any child element that contains an anchor, it inherits the styles specified.
You may also use the child selector as well since you'll have to specify the parent element anyway.
ul>li a {
property:value;
}
In this example, the anchor must be a descendant of an li that MUST be a child of ul, meaning it must be within the tree following the ul declaration. This is going to be a bit more specific and will only grab a list item that contains an anchor AND is a child of ul.
SO, to answer your question by code.
ul.menu > li a.active {
property:value;
}
This should grab the ul with the class of menu, and the child list item that contains only an anchor with the class of active.
I had the same problem with Drupal. Given the limitations of CSS, the way to get this working is to add the "active" class to the parent elements when the menu HTML is generated. There's a good discussion of this at http://drupal.org/node/219804, the upshot of which is that this functionality has been rolled in to version 6.x-2.x of the nicemenus module. As this is still in development, I've backported the patch to 6.x-1.3 at http://drupal.org/node/465738 so that I can continue to use the production-ready version of the module.
Many people answered with jQuery parent, but just to add on to that I wanted to share a quick snippet of code that I use for adding classes to my navs so I can add styling to li's that only have sub-menus and not li's that don't.
$("li ul").parent().addClass('has-sub');
I actually ran into the same issue as the original poster. There is a simple solution of just using .parent() jQuery selector. My problem was, I was using .parent instead of .parent(). Stupid mistake I know.
Bind the events (in this case since my tabs are in Modal I needed to bind them with .live instead of a basic .click.
$('#testTab1 .tabLink').live('click', function() {
$('#modal ul.tabs li').removeClass("current"); //Remove any "current" class
$(this).parent().addClass("current"); //Add "current" class to selected tab
$('#modal div#testTab1 .tabContent').hide();
$(this).next('.tabContent').fadeIn();
return false;
})
$('#testTab2 .tabLink').live('click', function() {
$('#modal ul.tabs li').removeClass("current"); //Remove any "current" class
$(this).parent().addClass("current"); //Add "current" class to selected tab
$('#modal div#testTab2 .tabContent').hide();
$(this).next('.tabContent').fadeIn();
return false;
})
Here is the HTML..
<div id="tabView1" style="display:none;">
<!-- start: the code for tabView 1 -->
<div id="testTab1" style="width:1080px; height:640px; position:relative;">
<h1 class="Bold_Gray_45px">Modal Header</h1>
<div class="tabBleed"></div>
<ul class="tabs">
<li class="current"> Tab Title Link
<div class="tabContent" id="tabContent1-1">
<div class="modalCol">
<p>Your Tab Content</p>
<p>tabBased Anchor Link </p>
</div>
<div class="tabsImg"> </div>
</div>
</li>
<li> Tab Title Link
<div class="tabContent" id="tabContent1-2">
<div class="modalCol">
<p>Your Tab Content</p>
<p>tabBased Anchor Link </p>
</div>
<div class="tabsImg"> </div>
</div>
</li>
</ul>
</div>
</div>
Of course you can repeat that pattern..with more LI's
Another thought occurred to me just now that could be a pure CSS solution. Display your active class as an absolutely positioned block and set its style to cover up the parent li.
a.active {
position:absolute;
display:block;
width:100%;
height:100%;
top:0em;
left:0em;
background-color: whatever;
border: whatever;
}
/* will also need to make sure the parent li is a positioned element so... */
ul.menu li {
position:relative;
}
For those of you who want to use javascript without jquery...
Selecting the parent is trivial. You need a getElementsByClass function of some sort, unless you can get your drupal plugin to assign the active item an ID instead of Class. The function I provided I grabbed from some other genius on SO. It works well, just keep in mind when you're debugging that the function will always return an array of nodes, not just a single node.
active_li = getElementsByClass("active","a");
active_li[0].parentNode.style.whatever="whatever";
function getElementsByClass(node,searchClass,tag) {
var classElements = new Array();
var els = node.getElementsByTagName(tag); // use "*" for all elements
var elsLen = els.length;
var pattern = new RegExp("\\b"+searchClass+"\\b");
for (i = 0, j = 0; i < elsLen; i++) {
if ( pattern.test(els[i].className) ) {
classElements[j] = els[i];
j++;
}
}
return classElements;
}

Resources