Why is this CSS rule being applied? - html

I have a page that uses jQuery UI for tabs, and I noticed some weird behavior in the Chrome inspector. Here's a screenshot showing the hierarchy up to the element in question, and the CSS rule that is being applied to it.
The CSS rule should apply to elements with class ui-widget-overlay, but the selected element does not have that class. Furthermore, toggling the background and opacity properties in that rule off and back on actually changes the page (when it obviously shouldn't). Is it some weird inspector bug or am I missing something here? It seems that it erroneously displays the rule that is completely irrelevant to the selected element, and toggling the properties makes them apply to the element when they previously weren't.

Related

Why does this globally defined css rule affect styling inside of the shadow DOM?

I created an web-component with shadow mode 'open', which is used like this:
<scu-switch checked="true" value="switch1">
<span id="scu-switch-label">Switch On</span>
</scu-switch>
and looks like this:
Than I added the button to a webpage with the following global CSS:
text-align: center;
and now the button style is broken:
When I inspect the button I can see, that the global style was applied to the span (and notice that it is not part of slot content) inside of the shadow root.
The shadow DOM is supposed to isolate style from the rest of the web page.
Why was this text-align: center applied here, even though it was defined outside of the Shadow DOM?
One of the great features of the Shadow DOM in Web Components is that styles are encapsulated to the component - you can style your component without worrying about any specifier (id, class, etc.) conflicts or styles 'leaking out' to other elements on the page.
This often leads to the belief that the reverse is true - that styles outside of the component won't cross the Shadow boundary and 'leak in' to your component. However this is only partly true.
While specifiers do not leak in to your component (e.g. a color applied to an p element in a style rule outside of your component won't effect any p elements in your Shadow DOM, although the rule will be applied to your Light DOM, or slotted content),
inheritable styles applied to any elements containing your component will be applied to both your Shadow and Light DOM.
Source: https://lamplightdev.com/blog/2019/03/26/why-is-my-web-component-inheriting-styles/

Why are different selectors shown for the same element based on how you select it in browser dev tools?

I know of multiple ways to determine a selector of an element in a browser code inspector:
locate the selector in the HTML pane of the inspector
hover over the selector in the HTML pane, and a tooltip will pop up that will show the selector, but that will be more verbose or different from the selector shown in the HTML pane
locate the selector that is not grayed out in the styles pane of the inspector
right click on the selector in the HTML pane, then click "copy selector", and that will be a selector with a higher specificity
Often all four of these have a different format or specificity.
Here is an example: the bbPress reply box. Selector #1 in the html pane, in the tooltip, if you hover the element:
textarea#bbp_reply_content.bbp-the-content.wp-editor-area
selector #2 copied as "CSS Selector" from the right-click menu of the element in the dev tools html pane:
div.wp-editor-container:nth-child(1) > textarea:nth-child(2)
#3 in the dev tools styles pane:
#bbpress-forums div.bbp-the-content-wrapper textarea.bbp-the-content
Three very different formats and with different specificity. Why are these all so different (including different specificity)?
Here is an example, the bbPress reply box. Selector #1 in the html
pane, in the tooltip, if you hover the element:
textarea#bbp_reply_content.bbp-the-content.wp-editor-area
I'm assuming you mean the HTML pane in the browser developer tools. The HTML view here is focused on the element that you are looking at, and will show the element name, any ID, and any Classes that might affect the selection (an ID must be unique, for example, and you can have lots of the same element with the same, similar, or completely different sets of classes applied). So the result you're getting here is contextualized to the view you're in, and what you're actually looking at:
ElementName.ID.ClassName(s)
You're not asking for a full selector to get this element, you're just asking for this exact element. Any ancestors are not important for what you're asking.
However, while this would be a valid selector, it's dangerous to refer to it as a selector for that very reason above; if you're looking for selector to use to target a specific element, this will miss out on all kinds of things in CSS that affect whether styles get applied. Cascading styles/precedence, specificity, and more could cause such a string to fail if used as a selector.
selector #2 copied as "CSS Selector" from the right-click menu of the
element in the dev tools html pane:
div.wp-editor-container:nth-child(1) > textarea:nth-child(2)
This is also a selector, and as you can see it's got more information before you get to the "textarea" element. However, it's still focusing on the "HTML content" context for that specific element... it doesn't care about IDs or classes that might be assigned to the final element. It's just saying "give me a CSS selector that, all else being equal, would select this element".
It's hard to say since it's a different element as the first example, and we can't see the full markup of the page you're using for your example, but I'm guessing this is a top-level div inside the body... either the only one, or the only one with that class. The browser is giving you just enough information to make sure you don't go down a different rabbit hole of elements by mistake.
Number 3 in the dev tools styles pane:
#bbpress-forums div.bbp-the-content-wrapper textarea.bbp-the-content
This is a CSS selector that someone wrote in a CSS file. It is showing up because it is a selector that applies to the element you selected. I'm sure there are more, even if they are just the default browser styles. For example, if you look in this location for an element on any Stack Overflow page, you'll probably see a whole host of entries:
While the other two are generated from the browser, this selector is one that a person decided to use and wrote out based on their desire for specificity and other qualifications for the styles they wanted to apply to this element.

How can I restore button default styles?

I'd like to reset a <button> to browser defaults in the high contrast mode of our website. Simply removing the styles is not an option as I would have to change a lot of code.
I thought this would be an easy task by assigning initial to every changed CSS property. Turns out, it doesn't work: while some properties are actually reset, the browser won't apply its original background-color and border and, in the case of Chrome, the text color when the button is disabled.
Is there a way to do this or can I only approximately reconstruct the browser defaults? And what is initial for if not for that?
JSFiddle showcasing the problem.
While some properties are actually resetted, the browser won't apply
its original background-color and border
It looks to me like the OP is looking for the revert value functionality.
See the spec regarding revert - one of the CSS-wide property values:
Rolls back the cascaded value to the user level, so that the specified
value is calculated as if no author-level rules were specified for
this property on this element. ...
Unfortunately, the revert value is currently not well supported.
Caniuse on revert actually nicely summarizes (and also hi lights the difference between revert and initial)
A CSS keyword value that resets a property's value to the default
specified by the browser in its UA stylesheet, as if the webpage had
not included any CSS. For example, display:revert on a <div> would
result in display:block. This is in contrast to the initial value,
which is simply defined on a per-property basis, and for display would
be inline.
I suppose your html for high contrast mode has a parent with a class... let's say as an example you have the class "highcm" at body
You could change your actual css sheet where you have styled your buttons to something like:
body:not(.highcm) .youractualclass button {
color: red;
}
This way just your button with not "highcm" at body will be styled while the rest will be rendered browser defaults

Shadow Dom and CSS3 :target selector

I should start off by saying that I don't really have an issue that I'm trying to work through. I just had an interesting thought about how Shadow Dom and the CSS3 :target selector might / should / currently do work together.
I know that HTML specification says that there should only ever be one element with a particular ID value in a valid HTML document. But when we start using webcomponents with shadow dom we could very easily find ourselves using multiple elements with the same ID. This is especially true when we use the same component multiple times in the same page. So the question that I have is this: what should happen to an element inside a shadow dom region that has an ID value which matches the current hash and which is styled with a :target rule?
For example, if I wrote a webcomponent (my-element) that contained
<style>
#debug {display:none}
#debug:target { display:block; background-color:yellow; border 2px solid red; }
</style>
<div id="debug">some debug data</div>
What should happen to all the instance of my-element that I put on a page and navigated to #debug on? Should the debug element in each component show? Should none of them show? Should only the first element's debug div show (the same one I'd expect the browser to try and navigate to)?
My opinion is that if the page does not have an element with an ID=debug value that no scrolling navigation should appear on the page. As shadow dom is isolated from the rest of the page's styles the browser shouldn't try to navigate to such an element nested in shadow dom. Each my-element instance should be able to see the current page's URL though and should apply any matching :target rules, such that each my-elements' debug div should be visible.
If this were the case it would make for some interesting possibilities for sharing page state across all components, such as the debug example above. However, I doubt that is how Chrome is currently implementing things. And I'm pretty sure this Shadow Dom polyfill isn't going to handle things correctly as it basically shoehorns everything into the page's Dom tree and that would break the html specification.
Just curious if anyone has an answer for how this should work and how it works today...
(edited from my pc to add formatting... hard to do from my phone)
I think you can see the shadow DOM like a nested document. CSS can't address elements inside the shadow DOM from the outside (previously existing shadow piercing CSS selectors were deprecated).
This also encapsulates ids and therefore multiple components that contain elements with an id won't cause collisions or duplicates.
If you have the CSS with the :target selector inside a components style, it should be able to address the element with the matching id, otherwise it shouldn't.
So the question that I have is this: what should happen to an element
inside a shadow dom region that has an ID value which matches the
current hash and which is styled with a :target rule?
Adding to Günter Zöchbauer above answer an alternative is to use the Custom Element object when the style is encapsulated, if the style is global it will work just fine. Use the define method to create a custom component as shown in the the docs. This will not encapsulate your elements so be aware that your styles can be shared across files.
So instead of doing this:
const shadow = this.attachShadow({ mode: "open" });
shadow.appendChild(pTag)
Use this:
this.appendChild(pTag);
both previous examples suppose you're in a HTMLElement class or a class that inherits it.

How do I learn what changes my css values?

I am a newbie (very much so), so my question might be dumb, but I couldn't find the answer.
For a contact table on a webpage I have set the height of 30px, but when I look at it in Google Developer tools, the height value is crossed out. I've tried to find out what causes my value to be overriden, but no luck. The developer tools shows that the value is overriden, but it doesn't show where.
So, the question is: How do I find what overrides my values in CSS?
In Chrome, your styles will inherit from any parent styles - either in the same style sheet or, if you have any, in other attached style sheets.
When a style inherits attributes either from parent elements or other classes, its predecessors will be listed in the Style Browser*, listed from nearest styles to most distant. So for example, if you have a paragraph that has a class assigned to it, but that paragraph is contained within a parent div that also has its own styles, your Style Browser will show the class name of that paragraph at the top (including all the class attributes), followed by the div's classes and so on up your DOM.
To discover which style is overriding your height value, scroll down through the Style Browser until you find a height attribute that isn't crossed out. You will also see the style sheet (including the line number) that contains the style that is affecting your page's appearance.
*You can open the style browser by right-clicking within a web page and selecting "Inspect Element".
You have to read the styles from the bottom going up.
You should find your CSS rule for the table in the styles section. Going up from that point you should be able to see which are the modifications that override your rule and display the element as depicted in the "Computed style" section.
If you dont find anything please give a look to your inline styles.
It would be easier to explain if I can look at some sample code...
The applied style is shown in the top and then the overridden ones are shown crossed out as you scroll down. So, the overridden value should be somewhere above the one which has been crossed out.