CSS Selector doesn't work as expected - css

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

Related

Target elements without *any* attributes?

Is there a selector method that allows policing whether, eg. the HTML tag is a clean "<html>" with no attributes whatsoever?
I'm trying to create a Stylish override sheet for browser-generated image pages in Firefox, but I essentially have to apply it to all URIs since such pages are always still ostensibly from the images' own domains.
The easiest way seems to be testing whether the HTML and Body tags have zero attributes (plus only-child and class selection on the image tag) because the structure of most documents which haven't been generated by the browser won't start as simply as <html><body><img class="...
But all I can find is how to exclude a specific attribute, not all of them.
I've tried the following with no success:
[] {
color: blue;
}
[*] {
color: red;
}
<p>Clean element with no attributes</p>
<p class="has-class">Has class attribute</p>
<p id="has-id">Has ID attribute</p>
<p data-has-data-attribute="">Has data attribute</p>
The only remaining option I can come up with is just policing the standard attributes one would see ("class", "style", "name", "lang", etc.), but that's a lengthy and ever-changing list, notwithstanding the numerous non-standard ones.
A selector that matches a tag without attributes doesn't currently exist.
I read through the latest CSS selector reference and couldn't find a selector that does what you wish.
You can't use an asterisk in the attribute selector to select everything unfortunately. These two railroad diagrams represent what is allowed:
So your first two attempts are invalid, and the valid empty string seems to have no effect:
[] {
color: blue;
}
[*] {
color: red;
}
[""] { /* Seems to select nothing, rather than 'no attribute' */
color: magenta;
}
<p>Clean element with no attributes</p>
<p class="has-class">Has class attribute</p>
<p id="has-id">Has ID attribute</p>
<p data-has-data-attribute="">Has data attribute</p>
I can't come up with any possible hack that doesn't involve JavaScript. I will edit this answer if I figure out a solution.

How to think about styling AngularJS components?

I'm working on an AngularJS project with the aim of slowly getting things in order for Angular 6, or whatever version is out when we start on the upgrade. One of the big pieces of that work is converting existing directives into components.
The thing I'm struggling the most with, is that every instance of a component introduces an extra element into the DOM that wraps my actual component HTML and breaks the hierarchy, making it very hard to write CSS that does what it needs to.
To illustrate my dilemma, imagine a simple component called alert that provides styling for various types of messages you want a user to pay attention to. It accepts two bindings, a message and a type. Depending on the type we will add some special styling, and maybe display a different icon. All of the display logic should be encapsulated within the component, so the person using it just has to make sure they are passing the data correctly and it will work.
<alert message="someCtrl.someVal" type="someCtrl.someVal"></alert>
Option A: put styling on a <div> inside the extra element
Component template
<div
class="alert"
ng-class="{'alert--success': alert.type === 'success', 'alert--error': alert.type === 'error'}">
<div class="alert__message">{{alert.message}}</div>
<a class="alert__close" ng-click="alert.close()">
</div>
Sass
.alert {
& + & {
margin-top: 1rem; // this will be ignored
}
&--success {
background-color: green; // this will work
}
&--error {
background-color: red; // this will work
}
}
This works fine as long as the component is completely ignorant of everything around it, but the second you want to put it inside a flex-parent, or use a selector like "+", it breaks.
Option B: try to style the extra element directly
Component template
<div class="alert__message">{{alert.message}}</div>
<a class="alert__close" ng-click="alert.close()">
Sass
alert {
& + & {
margin-top: 1rem; // this will work now
}
.alert--success {
background-color: green; // nowhere to put this
}
.alert--error {
background-color: red; // nowhere to put this
}
}
Now I have the opposite problem, because I have nowhere to attach my modifier classes for the success and error states.
Am I missing something here? What's the best way to handle the presence of this additional element which sits above the scope of the component itself?
I personally do option A. This allows you to easily identify and create specific styles for your components without fear that they will overwrite site-wide styles. For instance, I'll use nested styles to accomplish this:
#componentContainer {
input[type=text] {
background-color: red;
}
}
This will allow you to make generic styles for your component that won't spill out into the rest of your solution.

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

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])

CSS attribute-value selector doesn't work if value contains hash # sign

Am using bootstrap LIKE dropdown menu with custom HTML5 attribute with data- as a prefix with a value starting from #, now for some reason I can't change this.
Here's the script link (It's like this dropdown)
Now the issue is am using dynamic approach using PHP so child of an element changes often so I am not using nth-child so thought of using attribute-value selector but CSS doesn't accept if value contains #. Any workarounds for this?
<div data-demo="works">This works</div>
<br />
<div data-demo="#doesnt_works">This fails</div>
CSS
div[data-demo=works] {
color: red;
}
div[data-demo=#doesnt_works] {
color: green;
}
Demo
Use quotes:
div[data-demo='#does_work'] {
color: green;
}
DEMO
Why it has to be quoted? Because # has special meaning in CSS. Quoting it hides that special meaning. The same effect could be approached using ": [data-demo="#does_work"] or by escaping # with \: [data-demo=\#does_work]
Wrap the value in quotes "
div[data-demo="#doesnt_works"] {
color: green;
}
http://jsfiddle.net/jeq5W/1/

CSS :after, content: having two values?

I've got CSS on my links depending what type of link it is. In this case it's password protected, and external link.
So I've got CSS like this:
a.external-link:after { padding-left: 2px; content: url(../images/icon-external-link.gif); }
a.restricted-link:after { padding-left: 2px; content: url(../images/icon-lock.png);}
However when I try something like this:
<a class="external-link restricted-link" href="some link">Some Link</a>
It only displays the last icon, in this case the icon-lock.png. Which makes sense, since the content value can only be set once not combined, so the last class declaration is overwriting it. Is there anyway to combine these two so I can mix and match these link classes easily (I've got 4 total). I don't want to make separate classes/images for each combo.
Hate to break it to you, but you're going to have to make separate classes/images for each combo. Especially as there would be no way of knowing which content should go first.
a.external-link.restricted-link:after
{
content: url(ext) url(res);
}
vs
a.external-link.restricted-link:after
{
content: url(res) url(ext);
}

Resources