Skip a child element - css

I don't want css to be applied to a child element.
<div id="main">
<div id="child">
<div id="subchild">
<p> subchild </p>
</div>
<p> child </p>
</div>
</div>
I want to apply css to all divs except the subchild div and its children.

To do this, simply apply the CSS to all divs and then reverse it for the subchild:
#child
{
display: inline;
background-color: black;
}
#child #subchild
{
/* Assuming this was blocked/transparent before the '.child' css applied. */
display: block;
background-color: transparent;
}

Related

Why does the sticky element not stick to the top when the flex element is full-width?

I have a flex div that contains two further elements. When viewed fullscreen on a desktop, one of the elements acts as a sidebar. On smaller screens, the elements collapse to be displayed one on top of the other.
This technique is explained on Every Layout.
I want to introduce a sticky element that will be used for navigation. On a wide screen, it works as expected. I can scroll the page and the sitcky element sticks to the top. However, in a narrower window, the element does not stick. It scrolls out of view – the same in both Safari and Firefox.
.with-sidebar {
display: flex;
flex-wrap: wrap;
}
.with-sidebar > :first-child {
flex-basis: 20rem;
flex-grow: 1;
background-color: green;
}
.with-sidebar > :last-child {
flex-grow: 999;
min-inline-size: 50%;
background-color: red;
}
.sticky {
position: sticky;
top: 1rem;
}
<div class="with-sidebar">
<div>
<h1>Sidebar</h1>
<div style="height:10rem">Spacer</div>
<div class="sticky">
<h1>Sticky Element</h1>
</div>
</div>
<div>
<h1>Not Sidebar</h1>
<div style="height:200rem">Spacer</div>
</div>
</div>
Among other things, I have tried wrapping the sticky inside another element, tried applying align-self: flex-start; to the sticky. I haven't yet found anything that works.
How can I ensure that the element is sticky when the sidebar and not-sidebar are stacked vertically as well as when they are alongside each other?
Update
I have experimented with placing .with-sidebar within a taller wrapper. Now it is clear what is happening. The element which is not the sidebar is pushing the sticky element off screen. This never happens when the elements are side by side. But, in a smaller window, the not-sidebar element is directly beneath the sticky element.
<div style="height: 400rem">
<div class="with-sidebar">
<div>
<h1>Sidebar</h1>
<div style="height:10rem">Spacer</div>
<div class="sticky">
<h1>Sticky Element</h1>
</div>
</div>
<div>
<h1>Not Sidebar</h1>
<div style="height:60rem">Spacer</div>
</div>
</div>
</div>
I think it's better to redo the markup (or design). See, for example, if you specify a height for a block, in which the "sticky element" is located, div:has(.sticky) { height: 500px; } then the element starts to "stick a little", or another example, change nesting
<body>
<div class="with-sidebar">
<div>
<h1>Sidebar</h1>
<div style="height: 10rem">Spacer</div>
<!-- <div class="sticky">
<h1>Sticky Element</h1>
</div> -->
</div>
<div class="sticky">
<h1>Sticky Element</h1>
</div>
<div>
<h1>Not Sidebar</h1>
<div style="height: 200rem">Spacer</div>
</div>
</div>
</body>
and add a property align-self for this element.
.sticky {
position: sticky;
top: 1rem;
align-self: flex-start;
}
But I don't think that's all for you. This is just an examples so you can see how the element works. The specification CSS Positioned Layout Module Level 3 very briefly describes the behavior of elements when positioned sticky.
Use media queries for top position if 10rem is not as you want...
.sticky {
position: fixed;
top: 10rem;
}
Update: I clarify my thoughts:
<div class="with-sidebar">
<div>
<h1>Sidebar</h1>
<div style="height:10rem">Spacer</div>
<div class="sticky_desktop">
<h1>Sticky Element</h1>
</div>
</div>
<div>
<div class="sticky_mobile">
<h1>Sticky Element</h1>
</div>
<h1>Not Sidebar</h1>
<div style="height:200rem">Spacer</div>
</div>
</div>
.with-sidebar {
display: flex;
flex-wrap: wrap;
}
.with-sidebar > :first-child {
flex-basis: 20rem;
flex-grow: 1;
background-color: green;
}
.with-sidebar > :last-child {
flex-grow: 999;
min-inline-size: 50%;
background-color: red;
}
.sticky_desktop {
position: sticky;
top: 1rem;
}
.sticky_mobile {
position: sticky;
top: 1rem;
color: violet;
}
.sticky_mobile>h1{
margin-block-start: 0;
margin-block-end: 0;
}
#media screen and (min-width : 656px ){
.sticky_mobile {
display:none;
}
}
#media screen and (max-width : 655px ){
.sticky_desktop {
display:none;
}
}

Using CSS, how to add a pseudo element before every odd child element that is "outside" of that child element?

I want to create a grid with two columns whose width will be equal. My base HTML code looks like this:
<div class="linkgrid">
<div class="gridentry">
Loooooooooooooong
</div>
<div class="gridentry">
Short
</div>
<div class="gridentry">
Meeeedium
</div>
</div>
In this example, the first and the second gridentry should lie in the the first row. The thrid gridentry should lie in the second row. All gridentrys should have the same width.
~~~
I came up with a solution that uses a CSS table. However, to make sure the row "breaks" after every second cell, it currently requires non-semantic elements to force these "row breaks":
.linkgrid {
display: table;
border-spacing: 2px;
table-layout: fixed;
width: 50%;
}
.gridentry {
display: table-cell;
background-color: red;
padding: 5px;
text-align: center;
}
.gridentry a {
color: white;
}
.THIS-SHOULD-BE-A-PSEUDO-ELEMENT-BEFORE-EVERY-ODD-CHILD {
/* I imagine a selector that looks somewhat like this:
.linkgrid .gridentry:nth-child(odd):outsidebefore {
*/
display: table-row;
}
<div class="linkgrid">
<span class="THIS-SHOULD-BE-A-PSEUDO-ELEMENT-BEFORE-EVERY-ODD-CHILD"></span>
<div class="gridentry">
Loooooooooooooong
</div>
<div class="gridentry">
Short
</div>
<span class="THIS-SHOULD-BE-A-PSEUDO-ELEMENT-BEFORE-EVERY-ODD-CHILD"></span>
<div class="gridentry">
Meeeedium
</div>
</div>
Is there a way to remove my <span>s from my HTML (because they do not have any semantics) and use a clever CSS selector that adds them as pseudo elements at the right positions instead?
I do know that :before will "create" a pseudo-element within the selected element. Is there a non-JavaScript, CSS-only way to add a pseudo-element outside of the selected element like required in this example?
Another edit: For all those familiar with the Chrome developer tools, I want my result to look somewhat like this in the DOM tree:
<div class="linkgrid">
::outsidebefore
<div class="gridentry">
Loooooooooooooong
</div>
<div class="gridentry">
Short
</div>
::outsidebefore
<div class="gridentry">
Meeeedium
</div>
</div>
...where the ::outsidebefore pseudo-elements should have the CSS property display: table-row;.
Update 2016-01-04: While this specific question remains unanswered, my original problem was solved another way: https://stackoverflow.com/a/34588007/1560865
So please only post replies to this question that answer precisely the given question.
Display Level 3 introduces display: contents:
The element itself does not generate any boxes, but its children and
pseudo-elements still generate boxes as normal. For the purposes of
box generation and layout, the element must be treated as if it had
been replaced with its children and pseudo-elements in the document
tree.
Then, you can:
Wrap each cell in a container element
Set display: contents to those containers
Add ::before or ::after pseudo-elements to those containers
The result will look like as if the pseudo-elements were added to the cell, but outside it.
.wrapper {
display: contents;
}
.wrapper:nth-child(odd)::before {
content: '';
display: table-row;
}
.linkgrid {
display: table;
border-spacing: 2px;
table-layout: fixed;
width: 50%;
}
.wrapper {
display: contents;
}
.wrapper:nth-child(odd)::before {
content: '';
display: table-row;
}
.gridentry {
display: table-cell;
background-color: red;
padding: 5px;
text-align: center;
}
.gridentry a {
color: white;
}
<div class="linkgrid">
<div class="wrapper">
<div class="gridentry">
Loooooooooooooong
</div>
</div>
<div class="wrapper">
<div class="gridentry">
Short
</div>
</div>
<div class="wrapper">
<div class="gridentry">
Meeeedium
</div>
</div>
</div>
Note display: contents is not widely supported yet, but works on Firefox.
The most straightforward way is using an actual table structure. That is, one table divided into rows, in which the entries sit.
Also, you had width:50% on the table, but I believe from the question text that you meant every table cell to be 50% wide, rather than the table taking up 50% of the window width; so I corrected that.
.linkgrid {
display: table;
border-spacing: 2px;
}
.gridrow { /* new */
display: table-row;
}
.gridentry {
display: table-cell;
background-color: red;
padding: 5px;
text-align: center;
width: 50%; /* moved */
}
.gridentry a {
color: white;
}
<div class="linkgrid">
<div class="gridrow">
<div class="gridentry">
Loooooooooooooong
</div>
<div class="gridentry">
Short
</div>
</div>
<div class="gridrow">
<div class="gridentry">
Meeeedium
</div>
</div>
</div>

How can I use hover in a child without the parent's hover being activated?

My code can add divs as child or sibling, I've created two classes and two :hover for each class but when I put the mouse on a child the parent hover is activated as well.
.Group {
background-color: white;
}
.Group2 {
background-color: white;
}
.Group:hover {
background-color: yellow;
}
.Group2:hover {
background-color: red;
}
<div class="Group">
root
<div class="Group">1st child
<div class="Group2">2nd child
<div class="Group">3rd child</div>
</div>
</div>
<div class="Group">1st child</div>
</div>
If you hover over a child element, you're also hovering over the parent, there's no way around that.
What you could do is set a different or additional class on the 1st child elements that don't have further children.
Highlighting background colors in nested blocks when hovering
If you are trying to activate the background colors of the nested div blocks, I think you might be looking for the following.
For the HTML, use distinct class names to identify each layer of nested div blocks:
<div class="Group">root
<div class="Group1">1st child
<div class="Group2">2nd child
<div class="Group3">3rd child</div>
</div>
</div>
<div class="Group1">1st child</div>
</div>
and the CSS:
.Group, .Group1, .Group2, .Group3 {
background-color:transparent;
}
.Group:hover {
background-color:yellow;
}
.Group1:hover {
background-color:pink;
}
.Group2:hover {
background-color:red;
}
.Group3:hover {
background-color:orange;
}
Demo fiddle: http://jsfiddle.net/audetwebdesign/Scr9G/
As you mouse over each nested div successively, the background color changes in sequence.
If you are trying to target a nested element with :hover without the effect bubbling up through the parent/ancestor blocks, you will need to use JavaScript/jQuery to create the selection rules that you need.
Quirky Hack Using <p> Tags
The following construction exhibits the behavior that the OP would like to see:
<p class="Group">root
<p class="Group">1st child
<p class="Group2">2nd child
<p class="Group">3rd child</p>
</p>
</p>
<p class="Group">1st child</p>
</p>
and the CSS is as before:
.Group {
background-color:white;
}
.Group2 {
background-color:white;
}
.Group:hover {
background-color:yellow;
}
.Group2:hover {
background-color:red;
}
Second demo fiddle: http://jsfiddle.net/audetwebdesign/cf2mn/
In this case, the OP was trying to nest <p> tags, which actually do not work like nesting other block elements like <div>.
When using <p> tags, the closing </p> tag is optional if followed by other flow elements like p, div, ul and so on.
In this case, the HTML snippet show above is equivalent to:
<p class="Group">root</p>
<p class="Group">1st child</p>
<p class="Group2">2nd child</p>
<p class="Group">3rd child</p>
<p class="Group">1st child</p>
which means that all the p tabs are siblings and there are no parent-child relationships, which is why the CSS appears to be working as the OP desired.
If div tags had been used instead of p tags, the resulting DOM would have exhibited the parent-child relationships and the CSS would have shown the original behavior that the OP did not want.
Using the p tags may give the desired effect for the CSS, but it works only because the DOM elements are siblings instead of parent-child. (In addition, the nested p tags will not validate.)
It is worth noting that:
CSS 2.1 does not define if the parent of an element that is ':active' or ':hover' is also in that state.
so it is better not to rely on the state of the parent element when apply a pseudo-element on a child element.
References:
About :hover: http://www.w3.org/TR/CSS2/selector.html#dynamic-pseudo-classes
About optional closing of p tag: http://www.w3.org/TR/html-markup/p.html#p
There's no way to prevent parent elements to get background color.. rather use this code
<div class="root">
Main Root
<div class="group">
First One
</div>
<div class="group2">
Second One
</div>
<div class="group">
Third One
</div>
.group:hover {
background: yellow;
}
.group2:hover {
background: red;
}
SEE THE DEMO HERE
Give separate ids to the divs and when a child div is hovered over, change its background image color and remove the background color of the parent all at the same time. I guess that is the only way around this
The simplest and best way is probably to use any other element, li for instance.
css:
.Group, .Group2, .Group3
{
background:white;
display: block;
list-style: none;
}
.parent
{
margin: 0;
display: block;
padding: 0;
}
.Group:hover
{
background: yellow;
}
.Group2:hover
{
background: red;
}
.Group3:hover
{
background: yellow;
}
html:
<ul class="parent" >
<li class="Group" >root
<li class="Group">1st child
<li class="Group2">2nd child
<li class="Group3">3rd child</li>
</li >
</li >
<li class="Group">1st child</li >
</li>
</ul>
You should add sub-element for content and use element+element pseudo selector.
.group-content:hover {
background-color: yellow;
}
.group-content:hover + .group {
background-color: red;
}
<div class="group">
<div class="group-content">1st child</div>
<div class="group">
<div class="group-content">2nd child</div>
<div class="group">
<div class="group-content">3nd child</div>
</div>
</div>
</div>
<div class="group">
<div class="group-content">1st child</div>
</div>

Show div inside a div if hovering

Would it be possible, with css only, that if I hover over the .post element the options show. If not I want it to be hidden.
<div class="post">
<div class="author">
Yxvasznalskje
</div>
<div class="options" style="display:none;">
Report - Delete
</div>
<p>Message</p>
</div>
Remove the inline display:none; and use .post:hover .options to select the inner div when the parent div is hovered:
.options {
display: none;
}
.post:hover .options {
display: block;
}
See DEMO.

how to add 2 overlapping elements in a div?

<div id="parent" style="height:250px;width:250px;display:inline">
<div id="child" style="height:100%;width:100%;z-index:10001"></div>
<select style="height:100%;width:100%;z-index:10000"><option/></select>
</div>
My requirement is to include the select and child div elements inside the parent div in such a way that the child div is on top of the select element and completely covers it. Later I want to hide the child div based on an event and make the select element visible.
Both child div and select elements should occupy the entire size of parent div each on their own.
how can I achieve this?
http://jsfiddle.net/dyBjZ/2
#parent {
position: relative;
overflow: auto;
}
.child {
position: absolute;
height:100%;
width:100%;
}
<div id="parent">
<div class="child">
<select>
<option>One</option>
<option>Two</option>
</select>
</div>
<div class="child" id="child">Click me</div>
</div>
Taking input from the comments above, I was able to solve my problem. Here is what I did. Posting it here in case someone else lands up on this page searching.
<div id="parent" style="height:250px;width:250px">
<div id="child" style="display:block;height:100%;width:100%"></div>
<div id="selectParent" style="display:none;height:100%;width:100%">
<select><option/></select>
<div>
</div>
Based on the javascript event, I toggle display from block to none for child div. And toggle display from none to block in selectParent.
First issue is to give the #parent div a size, thus remove display: inline from its style.
Next, you could toggle for both elements from display: none to display: block, and v.v. But to reduce this by half, you could use absolute positioning which takes the element out of the default markup layout, as shown in this example.
HTML:
<div id="parent">
<div id="child"></div>
<select></select>
</div>
CSS:
#parent {
height: 250px;
width: 250px;
position: relative;
}
#child {
position: absolute;
background: #aaa;
height: 100%;
width: 100%;
}
select {
height: 100%;
width: 100%;
}
#child.hidden {
display: none;
}

Resources