I have this issue where I need to apply some style to a div only if it's next to a visible item (even if there's non visible items in between, but not if all the items following the current one are all invisible), as shown here:
https://stackblitz.com/edit/js-3nulnw?file=style.css
.container {
display: flex;
flex-grow: 1;
padding: 5px;
}
.content {
border: 1px solid #000000;
border-radius: 4px;
width: 50%;
padding: 10px;
}
.addon {
width: 10%;
background-color: #ff0000;
border: 1px solid #000000;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
border-left: none;
}
.addon.hidden {
display: none;
}
.content:not(:last-child),
.addon:not(:last-child) {
border-right: none;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
<div >
<div >This is shown correctly (no addons)</div>
</div>
<div >
<div >This is shown correctly (one addon)</div>
<div ></div>
</div>
<div >
<div >
This is shown correctly (multiple addons, one is hidden)
</div>
<div ></div>
<div ></div>
</div>
<div >
<div >This is shown correctly (multiple addons)</div>
<div ></div>
<div ></div>
</div>
<div >
<div >This should have all rounded borders</div>
<div ></div>
</div>
<div >
<div >This should have all rounded borders</div>
<div ></div>
<div ></div>
</div>
I have tried looking on the internet but to no avail, but I'm probably looking for the wrong answer (most of what I found were other SO questions saying there's no CSS selector for non visible item), so alternative ways to do this are welcome (possibly without JS)
CodePudding user response:
Yes it is possible. I try to understand your question and get this result. Please expalin more your question https://developer.mozilla.org/en-US/docs/Web/CSS/:is
We can get it through (:is) pseudo-class function. we can check if div has class like visible in below example case then we can apply style to its next div throught ( ) adjacent sibling selector or (~) general sibling selector. I hope example will clear what I want to say
<div >
<div >This is shown correctly (no addons)</div>
</div>
<div >
<div >This is shown correctly (one addon)</div>
<div ></div>
</div>
<div >
<div >
This is shown correctly (multiple addons, one is hidden)
</div>
<div ></div>
<div ></div>
</div>
<!-- [ADD 'visible' CLASS BEFORE OF TARGET CONTAINER] -->
<div >
<div >This is shown correctly (multiple addons)</div>
<div ></div>
<div ></div>
</div>
<div >
<div >This should have all rounded borders</div>
<div ></div>
</div>
<div >
<div >This should have all rounded borders</div>
<div ></div>
<div ></div>
</div>
and its css will be
.container {
display: flex;
flex-grow: 1;
padding: 5px;
}
.content {
border: 1px solid #000000;
border-radius: 4px;
width: 50%;
padding: 10px;
}
.addon {
width: 10%;
background-color: #ff0000;
border: 1px solid #000000;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
border-left: none;
}
.addon.hidden {
display: none;
}
.content:not(:last-child),
.addon:not(:last-child) {
border-right: none;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.container:is(.visible) .container{
background-color: rebeccapurple;
color: white;
/* Your style here */
}
.container:is(.visible) .container .addon{
background-color: brown;
color: white;
/* Your style here */
}
CodePudding user response:
I found a horrible but apparently effective way of achieving what I wanted
https://stackblitz.com/edit/js-4hkorq?file=style.css
.container {
display: flex;
flex-grow: 1;
padding: 5px;
}
.content {
border: 1px solid #000000;
border-radius: 4px;
width: 50%;
padding: 10px;
}
.addon {
width: 10%;
background-color: #ff0000;
border: 1px solid #000000;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
border-left: none;
}
.addon.hidden {
/* display: none; */
visibility: hidden;
width: 0px;
}
.content:not(:last-child),
.addon:not(:last-child) {
border-right: none;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.container > div:last-of-type.hidden::before {
content: '';
border: 1px solid #000000;
border-radius: 4px;
border-left: none;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
height: 100%;
display: flex;
width: 4px;
visibility: visible;
position: relative;
top: -1px;
}
.container > .addon div:last-of-type.hidden::before {
background-color: #ff0000;
}
<div >
<div >This is shown correctly (no addons)</div>
</div>
<div >
<div >This is shown correctly (one addon)</div>
<div ></div>
</div>
<div >
<div >
This is shown correctly (multiple addons, one is hidden)
</div>
<div ></div>
<div ></div>
</div>
<div >
<div >This is shown correctly (multiple addons)</div>
<div ></div>
<div ></div>
</div>
<div >
<div >This should have all rounded borders</div>
<div ></div>
</div>
<div >
<div >This should have all rounded borders</div>
<div ></div>
<div ></div>
</div>
The trick is to use visibility: hidden and width: 0 instead of display: none, then add a ::before pseudo element that adds the border. It has the drawback of adding 4 pixels to the element (in order to have a 4 pixels border radius it needs to be at least 4 pixels wide) but it is acceptable in my case and (albeit with some tweaks) it also worked in my application.
For some reason I had to add top: -1px because it wouldn't align otherwise, but in my application I didn't need to do
CodePudding user response:
These are the major changes to CSS
.container {display: table; table-layout: fixed; width: 100%...} .addon {display: table-cell; position: relative; right: 5px; z-index: 1; padding-right: 5px;...} .addon .addon {right: 10px; padding-right: 10px;...} .content {display: table-cell;}
Since this is a pure CSS solution, the tags were changed so that :*-type-of works effectively. If you want a uniform height, add a div inside .content and give it an absolute height (ie px)
section:first-of-type > div {
border-top: 1px solid #000000;
}
section:last-of-type > div {
border-bottom: 1px solid #000000;
}
.container {
display: table;
table-layout: fixed;
width: 100%;
}
.content {
display: table-cell;
padding: 15px;
width: 50%;
border-left: 1px solid #000000;
border-right: 1px solid #000000;
border-top: 0.5px solid #000000;
border-bottom: 0.5px solid #000000;
border-radius: 4px;
}
.addon {
display: table-cell;
width: 10%;
position: relative;
right: 5px;
padding-right: 5px;
z-index: 1;
background-color: #ff0000;
border-left: 0;
border-right: 1px solid #000000;
border-top: 0.5px solid #000000;
border-bottom: 0.5px solid #000000;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
.addon.hidden {
display: none;
}
.addon .addon {
right: 10px;
padding-right: 10px;
}
<section >
<div >This is shown correctly (no addons)</div>
</section>
<section >
<div >This is shown correctly (one addon)</div>
<aside ></aside>
</section>
<section >
<div >
This is shown correctly (multiple addons, one is hidden)
</div>
<aside ></aside>
<aside ></aside>
</section>
<section >
<div >This is shown correctly (multiple addons)</div>
<aside ></aside>
<aside ></aside>
</section>
<section >
<div >This should have all rounded borders</div>
<aside ></aside>
</section>
<section >
<div >This should have all rounded borders</div>
<aside ></aside>
<aside ></aside>
</section>
