Visual Composer: nth-child not working with css classes - html

I am working on a website for a client, and she has Visual Composer installed. For a post grid, I need to assign a different color to each post title. My approach was to find the grid-item container and append :nth-child to it, then direct it to the custom css class I really want to apply the different color to.
Example code, based on the actual code:
.vc_grid-item:first-child > ... > vc_gitem-zone-a > ... > .custom-post-title {
background-color: red;
}
.vc_grid-item:nth-child(2) > ... > vc_gitem-zone-a > ... > .custom-post-title {
background-color: green;
}
.vc_grid-item:nth-child(3) > ... > vc_gitem-zone-a > ... > .custom-post-title {
background-color: blue;
}
Strangely enough, this technique worked fine for the hover-text effect over the post's featured image.
I tried nth-of-type, but had little luck with it. It would work, but only parsed the first or second of type, applying the same color to all three divs.
I have tried every path permutation I can think of, but not a single one works.
Trying to track down a path through the endless divs that Visual Composer generates is practically impossible. Using the code inspector (Google Chrome), I found dynamically generated classes, classes injected as inline styles, and classes that were in the rendered HTML, but nowhere to be seen in the inspector. After several hours of carefully mapping out different "class paths" to make this work, I gave up out of sheer frustration.
Interestingly enough, the Visual Composer documentation is clear that, by adding custom css classes through its UI, custom styling is easy and straightforward. My experience is that this is true--if you want to apply the same color to all your divs in the post grid. Try customizing each grid-item independently, though, and it's a whole different ball game...one that may be impossible to win.
Any ideas as to how I might get this to work without resorting to some kind of hacky JavaScript black magic?

If you want to target a series of elements with the class .vc_grid-item, what you need is :nth-of-class... and it doesn't exist.
If you state the type of element, then you can use :nth-of-type:
div:nth-of-type(3).vc_grid-item > ... > .custom-post-title {background-color: blue;}
N.B. This sort of thing will be much easier when CSS4 :nth-match arrives.
Then, in this kind of situation, you will be able to use:
:nth-match(3 of '.vc_grid-item')
Further Reading: http://www.w3.org/TR/selectors4/#selected-child-index

child point to tbody in table
you must use tbody in selector for pointing child to tr
.vc_grid-item tbody :nth-child(1){
background-color: green;
}
.vc_grid-item tbody :nth-child(2){
background-color: blue;
}

Related

Can you set body id dynamically in React?

I am trying to implement dark mode in my app.
The idea is to add this to the root element:
<div id="dark">
And then this in CSS:
#dark {
background-color: #1A1A2E;
}
And then in Css, customize each dom element by using classes. For example, here I will work on cards:
#dark .card-body {
background-color: #16213E !important;;
}
#dark .card-header {
background-color: #0F3460 !important;
}
Now, this works perfectly fine.
But, with Modals, it does not work. I think it's because Modals are not rendered initially so for some reason the dark style does not apply to them.
What worked though is adding id="dark" to each modal:
#dark .modal-header {
background-color: #0F3460 !important;
}
#dark .modal-body {
background-color: #16213E !important;;
}
#dark .modal-footer {
background-color: #16213E !important;;
}
<Modal
// dark doesn't get applied automatically for modals because apparently modals are not rendered in the beginning
id="dark"
isOpen={this.state.isModalOpen}
toggle={this.toggleModal}
>
<div className="modal-header">
But, it'll be a pain to apply this to every single modal.
One solution mentioned here:
Modal should be the descendant of a tag which has id="dark". It is
loaded by the script right below the script tag and you are trying to
put 'dark' id on some div tag and the modal doesn't lie inside it,
thus the CSS selector not targeting it.
So, you need to put id="dark" on the body tag.
This solves the modals issue.
But, the problem is in my original implementation of dark mode, I am controlling that id in the root component like this:
// Root component
<div id={this.state.should_enable_dark_mode ? "dark" : "default"}>
And should_enable_dark_mode is managed like this:
manageDarkMode() {
window.addEventListener("storage", () => {
console.log("change to local storage!");
let should_enable_dark_mode = localStorage.darkMode == "true";
this.setState({
should_enable_dark_mode,
});
});
}
So the problem with the solution mentioned above is that I couldn't find a way to control the body tag from the react app. And I am not sure if it's a good thing to do.
What do you think I should do?
I see in the comments to your original question that you decided to just modify the body element in the browser DOM, which will probably work fine since the body element is not controlled by React and will likely not be changed by any other code.
I would however like to suggest a few improvements that makes it at bit less dirty:
use a data attribute like data-display-mode="dark" as a target for your CSS selectors instead of the ID. IDs are supposed to be stable and other tools and libraries (e.g. UI test tools) might rely on this.
use the Modal.container property to attach your Modals to the App element (the React-controlled global parent div defined in your React code, which you can control, not the app-root-div in index.html). Then set your data-display-mode attribute here by React-means. This way you will not bypass the virtual DOM.
use CSS custom properties for defining your colors, and then define all dark mode modifications in one place. Don't spread your dark-mode-styling code across multiple class selectors - you will have a hard time maintaining this.

How Can The Root Node Of A Horizontally Oriented PrimeFaces Tree Be Hidden?

The question says it all. When the tree is presented vertically the root node is not displayed. Setting rendered to false does not do it.
Well, as usual, CSS comes to the rescue. A simple attempt with a browser developer tool on the PrimeFaces showcase (I don't use the horizontal tree myself), with putting a css display:none directly on the first html element with class of ui-treenode node html makes it disappear, including the first line.
But there are childnodes in there... Putting a display:none on the first html node with a class of ui-tree-content makes the content of the first node disappear and keep the line in tact and the rest of the tree still functions fine.
So we already effectivly know it can be done...
The only thing needed then is a 'full' selector. The folling hides ALL nodes, not what you want.
.ui-tree .ui-treenode > .ui-treenode-content {
display: none;
}
So the selector should be improved. Adding all intermediate elements to the first node is a solution
.ui-tree > table > tbody > tr > .ui-treenode > .ui-treenode-content {
display: none;
}
(replacing the table, tbody and tr with a * would work too). But a more advanced solution where you actually select the first node with a class .ui-tree-nodeis
.ui-tree .ui-treenode:first-child > .ui-treenode-content {
display: none;
}
And if you e.g. only want it on a specific horizontal tree, add a class to that tree (e.g. no-root) and use it in the selector as well
.no-root.ui-tree .ui-treenode:first-child > .ui-treenode-content {
display: none;
}
What I effectively did here was (to try to) apply basic css knowledge and it provided a solution. Remember, client side it is (99.5% of the time) all html, css and javascript!!!
See also:
See also:
How do I override default PrimeFaces CSS with custom styles?

Overriding class definitions with Less

I'm trying to customize a Joomla template, which is based on Bootstrap. Specifically, I'm trying to make a "hardcoded" .span4 have the width of a .span3. Sure, it would be much easier to change the markup, but I think that's what css is for, despite the way most of us use Bootstrap for defining layout and visual appearance. Besides, where would be the fun of learning?
For that, this is what I'm trying in the my_css.less provided with the template:
.row-fluid #top1.span4 {
.row-fluid .span(3);
background:red;
}
Actually, the "background" bit is only to make sure that I'm not getting the selector wrong. So, I get that element with a red background, but the rest of the properties aren't applied. This is what I get instead:
.row-fluid .span4 {
width: 31.623931623932%;
}
Am I doing anything wrong? Is what I'm trying even possible?
Thank you!
* Edit *
This is the template I'm using in my page:
Perty by SmartAddons
The bit I'm trying to customize is the one at the right of the logo, the one holding the language selector and the social icons.
My client's logo is wider than the one in the template example, so it pushes #top1 to the right, and it pushes the following element (the one containing "galleries", "my account" and the search box) below.
Answering #Harry's question about selectors not matching, mine is ".row-fluid #top1.span4" because I only want my modification to apply to the .span4 contained in #top1. The other piece of code I pasted below is what is being applied instead of what I intend. Also, I wanted my customization to take preference over the default css, so my selector tries to be more specific. It doesn't seem to be wrong, because the background of the element becomes red.
#Harry:
Also, are you using any mixins to generate the width?
I'm not experienced in Less and I wasn't able to find the mixin in bootstrap documentation, but according to #freejosh at this post:
In mixins.less there's a mixin called .span(#columns) that's used to calculate the width, depending on #gridColumnWidth and #gridGutterWidth along with the argument.
Actually, that example is the one I'm trying to adapt to my needs.
I hope my edition made things clearer (or at least not more obscure, english is not my native language).
Thank you again!
* Edit 03/09/2014 *
Ok, I think I'm gettin closer. New code:
.row-fluid #top1.span4 {
#grid > .fluid > .span(3);
background:red;
}
Resulting css:
.row-fluid #top1.span4 {
width: * 3 * 2;
background: red;
}
Of course, the browser complains of an invalid property value. But at least that is a step (forward?)
#grid > .fluid > .span(3);
gives me:
.row-fluid #top1.span4 {
width: 23.40425532%;
*width: 23.35106383%;
background: red;
}
and NOT width: * 3 * 2;
Tested with less.php, less v1.4, v1.7.3. Notice that Less v2 do not compile BS2 at all.
Less v2 fails on #grid > .core > .span(#gridColumns); in navbar.less

Is it necessary to have a CSS selector of an ID within an ID?

For the purpose of this demo, I'll use a StackOverflow element for credibility.
If you sign out of SO, you can see a large call to action box at the top of the page. Even easier, just go to their new Portuguese version here - https://pt.stackoverflow.com/
Once you see the call to action box (captured below) go ahead and inspect it with developer tools.
On the div with the ID of hero-content, you will notice a style that I have pasted below:
#herobox #hero-content {
background: #fff7d8;
border: none;
}
I have done some research and as we all know, div ID's should be unique to the page. Although, if they are unique, why would a selector need to state an ID within an ID?
There are a couple of reasons.
Stylesheets can be reused between HTML documents. You may wish to distinguish between #hero-content that is a descendant of #herobox one page and of #somethingelse on another page.
The more likely one in this case is specificity. Assuming, for example, that #hero-content is a <div>, a general rule to set the styling of #herobox div would be more specific that #herobox #hero-content. Adding an extra id selector would increase the specificity.
It might be simply to increase the specificity of that selector.
For example, the author may have wanted to override...
#hero-content { border: 2px solid #333; }
It could also be a side effect of a tool like LESS, where the author may have originally written...
#herobox {
// Lots of other CSS.
#hero-content {
// ...
}
// Lots of other CSS.
}

CSS Conflicting Style Sheets

I have two style sheets which conflict with each other on several counts. Because I'm using 5, 6, and in some cases 9 or 10 complete plug-ins, each with three or fours style sheets, along with my own, conflicts arise everywhere. What is the best way to fix this problem? Is the only option to go in and modify the selectors of all of the plug-ins?
Edit: The problem is that all the plug-ins use their own style sheets which conflict with each other. The optimal, but probable impossible without modifying all the selectors, solution would to easily localize the style sheets to certain parts of the page.
keep in mind some very basic tips for style overriding:
First, try to avoid generic class names and id's that are certain to be used by other sources.
Second, !important can override styles, but should only be used in ways that make sense...
Third, the hierarchy of the "cascade" part of css is down -> out:
So
#header a{
color:#fff;
}
#header div a{
color:#000;
}
#header div.some-class a.active{
color:#ff0000;
}
The bottom selector will take priority no matter where it is placed because it is targeted specifically with a horrid chain of selectors. So perhaps you need to write your css in a way that reduces the chances of being overwritten by other sources.
The best way is definitely not to modify the selectors of the plugins unless you wrote the plugins yourself. You should modify your own classes/ids/css files to... not have conflicts.
Make your CSS as specific as possible, I would not modify the plugin unless you are confident you know your way around.
Wrap each section that you want to localise in its own div, with a specific and appropriate ID. Then mod each selector in the stylesheet to be preceded by #specificSectionID . With find/change in a decent code editor, you'll be done in five minutes. Example:
.headersection a {color: #DDD; background: transparent}
//becomes
#topSection .headersection a {color: #DDD; background: transparent}