What CSS operators can I use to add more page names? Wildcards? - css

I need to add more page name values beyond, "details". What are my options?
:host([page=details]) .menu-btn {
display: none;
}
:host(:not([page=details])) .back-btn {
display: none;
}
I should add that the "page" variable is a js property in my html file. I'm asking here because I don't even know what terms to use in my google search.

Thank you Greg McMullen, for pointing me to the documentation on attribute selectors.
Below is the solution that worked for all page values beginning with "details-". (Notice the vertical pipe in front of the equals and no trailing hyphen after"details".) For example, values including, "details-1", "details-2", and "details-3".
:host([page|=details]) .menu-btn {
display: none;
}
:host(:not([page|=details])) .back-btn {
display: none;
}
Technically, in my case, the "page" variable is not a html element attribute, in the strict definition.

The , CSS "combinator" allows you to set up multiple selectors and acts as an "and"/"or" operator so that you can specify several selectors that should all share the same rule:
:host([page=details]), :host([page=details2]), :host([page=details3]) { . . .}
And, you can just specify the attribute itself (no value) to match all elements that simply have the attribute (regardless of the value):
:host([page])

Related

Add logic to CSS

I would like to use logic in my CSS. Styles need to be applied only if a product ID is higher than a specific number, e.g:
if (data-product-id > 25) {
padding: 50px;
}
Is this possible with CSS?
No, it isn't. Attribute selectors are based on simple string matching. There is no provision for less than / greater than numerical comparisons.
The closest you could get with CSS itself would be something like:
[data-product-id="25"],
[data-product-id="26"],
[data-product-id="27"],
/* etc */
This sort of thing is better handled with JS or server-side code which adds classes to elements.
You can apply some limited logic of the like you were asking about in CSS, but I advise against it. Nevertheless, the answer below is an answer, it's better to implement your logic in Javascript.
Assuming that you have a class called data-product for all your data products, you can create this rule:
.data-product {
padding: 50px;
}
.data-product[data-product-id="1"],
.data-product[data-product-id="2"],
.data-product[data-product-id="3"],
.data-product[data-product-id="4"],
.data-product[data-product-id="5"],
.data-product[data-product-id="6"],
.data-product[data-product-id="7"],
.data-product[data-product-id="8"],
.data-product[data-product-id="9"],
.data-product[data-product-id="10"],
.data-product[data-product-id="11"],
.data-product[data-product-id="12"],
.data-product[data-product-id="13"],
.data-product[data-product-id="14"],
.data-product[data-product-id="15"],
.data-product[data-product-id="16"],
.data-product[data-product-id="17"],
.data-product[data-product-id="18"],
.data-product[data-product-id="19"],
.data-product[data-product-id="20"],
.data-product[data-product-id="21"],
.data-product[data-product-id="22"],
.data-product[data-product-id="23"],
.data-product[data-product-id="24"],
.data-product[data-product-id="25"] {
padding: 25px;
}

Target element by id somewhere within an element targeted by id

I'm trying to target an element by ID somewhere within an element which I have successfully targeted.
So this is the actual working CSS now:
#parentElement>div>div>div>#childElement {
display: none;
}
I'm sure I must be having a bad day but what I really want to do, to make it a little more robust is just write CSS (not jQuery or JavaScript) to do the following:
for all #childElement within #parentElement apply { display: none; }.
Is this a straightforward bit of CSS?
If you want all #childElement within #parentElement apply { display: none; }
just write
#parentElement #childElement { display: none; }
It will be enough.
But you should knew, id recommended to bu unique, used only once per page. Use class instead for children.

Excluding several pages from styling by CSS

I have some style that is supposed to be applied on all pages except three of them. It work fine for one page when I use
body:not(.home) #menu-footer{
color:green;
}
but how does it work for my other two pages (page-id-6 and page-id-7)? I tried this
body:not(.home) #menu-footer, body:not(.page-id-6) #menu-footer, body:not(.page-id-7) #menu-footer{
color:green;
}
but its not working.
body:not(.home) #menu-footer,
body:not(.page-id-6) #menu-footer,
body:not(.page-id-7) #menu-footer { … }
This doesn’t work, because when the body does have the class page-id-6, the other parts become true - you have a body that matches body:not(.home) now*, so the first part of this selector applies.
Apply all your “nots” at the same time instead:
body:not(.home):not(.page-id-6):not(.page-id-7) #menu-footer
This only applies when the body has neither of those three classes.
* Assuming of course, that only one of those classes is ever going to be set, but I guess that can be implied from the context of your question here.
Why not use a class for those pages you want to apply same styling to, in this case page ids 6 & 7, then apply a style. Here I'm using common_pages;
common_pages{
Color: green;
}

CSS Selector doesn't work as expected

I am developing a website which relies on user input to create scripts
As a defense in depth solution I am adding a blacklist protection to omit all links with an external source. I tried the following code snippet but it doesn't work (my browser supports it because w3schools sample works on it) :
[href~=//]
{
display: none;
}
There's a subtle different in the selectors that you are using :
[attribute~="value"] - This checks for a specific word (i.e. wrapped in white-space or the exact string)
[attribute*="value"] - This checks if a given set of text is contained at all.
You'll see that the second approach works, whereas the first does not.
Additionally, you'll want to ensure that you have the specific element you are targeting and that you are wrapping your value within quotes, as seen below :
a[href*='//']{
display: none;
}
Example
a[href*='//'] {
display: none;
}
/* Added to demonstrate selector differences */
a[href~='//'] {
color: green;
display: block;
}
<h4>[href*="value"] Examples</h4>
<a href='http://www.google.com'>Hidden</a>
<a href='stackoverflow.com'>Shown</a>
<a href='Check // this out'>Green</a>
<h4>[href~="value"] Examples</h4>
<a href='a//'>Hidden (since not whole "word")</a>
<a href='//'>Shown (as exact)</a>
<a href='//a'>Hidden (since not whole "word")</a>
Try this:
a[href*="//"]{
display:none;
}
Select all a objects whose href contains '//'
working fiddle

Target dynamic IDs like #event_rules_attributes_0_interval, #event_rules_attributes_1_interval, etc. with CSS3

It is very convenient to style input tags using their IDs as they have more precedence weight than classes have.
For example, I have a default width for input.text elements in a specific container:
.details .metadata input.text { width: 200px; }
To change the width for a specific page, it's more convenient to use the ID instead of the long selector above:
#my_input { width: 150px; }
Now I have automatically generated input fields somewhere in my app (generated using form_for and nested_attributes_for in Ruby On Rails) which generates IDs like so:
#event_rules_attributes_0_interval
#event_rules_attributes_1_interval
#event_rules_attributes_2_interval
...etc...
and
#event_rules_attributes_0_count
#event_rules_attributes_1_count
#event_rules_attributes_2_count
...etc...
So I need to use an ID selector like "begins with event_rules_attributes_" AND "ends with _count" or "begins with event_rules_attributes_" AND "ends with _interval". I know that there are the [id$=] and [id^=] matchers, but can they be combined somehow?
Just found it out myself:
[id^='event_rules_attributes_'][id$='_interval'] { width: 150px; }
Seems a bit ugly, but works.

Resources