I have 4 divs, all of them have their background image. When I hover one of them, that background image should spread over the all divs. Attached is example of how it should work.
How can I achieve this effect with CSS?
example:
.container{
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
}
.card{
height: 500px;
width: 250px;
}
.first{
background-color: red;
}
.first:hover ~ .card{
background-color: red !important
}
.second {
background-color: blue;
}
.third{
background-color: yellow;
}
.fourth{
background-color: green;
}
<div class="container">
<div class="card first"></div>
<div class="card second"></div>
<div class="card third"></div>
<div class="card fourth"></div>
</div>
In this case all the Cards are "siblings" cause they are all direct child elements of container. The ~ selector is for "siblings" there are definetly more elegant solutions for this with SCSS but this generally describes how it works, also look at the following post describing all kinds of Selectors depending on their heritage:
Post
Related
I am looking at having a header to a horizontal scrollable section that would have a date counter along the top, spanning the length of a year. Each date is represented by a single div. Weekends have a background color that is different than the week days. I am not using any graphics library, just straight HTML, CSS and JS. It is preferable that I do not need to change this.
My goal is to make it so that the weekend background color will extend down the main body of the panel without disrupting the layout and elements present there. The end result would look something like this:
Things I thought could potentially work:
Extend the background color of the weekend cells so that they continue vertically down the height of the main panel. This requires that background colors of cells can extend beyond the bounds of an element
Have the panel show different background colors at certain intervals. This would require the ability to alternate the background color of the SAME div multiple times
I am definitely open to any other ideas if I am simply unware of a better way to do things.
Optimization is a key concern, as I am expecting to have a couple of hundred rows of data (in a vertically scrollable div) as well as 300+ columns (in a horizontally scrollable div). I have run a test to determine if it was still responsive enough with a div per cell. The answer was most definitely not: it took seconds to load, it was laggy with the scrolling and overall just not nice to use. Not particularly surprising at 60,000 elements.
I have tried doing the following:
Doing a transform and pseduo selector on the weekend elements to extend the background (have had trouble with the :after element also extending the size of the current element). I've also had a problem trying to get the :after selector to apply down rather than to the right, even after trying some basic transforms
Making the entire thing discrete and adding divs for every representable day of a row. This was awful and unfortunately unusable at the scale I am expecting, but technically has the desired appearance
Sample code that can used to get a similar situation to my current environment:
#mainPanel {
overflow-x: scroll;
display: flex;
height: 100vh;
flex-direction: column;
}
#header {
height: 25px;
box-sizing: border-box;
display: flex;
flex-direction: row;
width: 100%;
}
.headCell {
height: 100%;
border: 1px #cccccc solid;
border-left: none;
box-sizing: border-box;
min-width: 25px;
display: flex;
align-items: center;
justify-content: center;
}
.weekend {
background-color: #efefef;
}
<div id="mainPanel">
<div id="header">
<div class="headCell">1</div>
<div class="headCell">2</div>
<div class="headCell">3</div>
<div class="headCell">4</div>
<div class="headCell">5</div>
<div class="headCell weekend">6</div>
<div class="headCell weekend">7</div>
<div class="headCell">8</div>
<div class="headCell">9</div>
<div class="headCell">10</div>
<div class="headCell">11</div>
<div class="headCell">12</div>
<div class="headCell weekend">13</div>
<div class="headCell weekend">14</div>
<div class="headCell">15</div>
<div class="headCell">16</div>
<div class="headCell">17</div>
<div class="headCell">18</div>
<div class="headCell">19</div>
<div class="headCell weekend">20</div>
</div>
<div id="panelBody">
Here is some text that will appear in the main div. I am hoping to see this not moved around and that the grey weekend lines will appear underneath the text.
</div>
</div>
Any help with concepts that could assist with this would be much appreciated, and any references to reading materials would be icing on the cake. Thanks a tonne in advance.
You can manipulate the .weekend::after pseudo element by adding this code:
.weekend::after{
content:'';
position:absolute;
height:100%;
width:25px;
top:1em;
z-index:-1;
background-color: #efefef;
}
Here is the full working code:
#mainPanel {
overflow-x: scroll;
display: flex;
height: 100vh;
flex-direction: column;
}
#header {
height: 25px;
box-sizing: border-box;
display: flex;
flex-direction: row;
width: 100%;
}
.headCell {
height: 100%;
border: 1px #cccccc solid;
border-left: none;
box-sizing: border-box;
min-width: 25px;
display: flex;
align-items: center;
justify-content: center;
}
.weekend {
background-color: #efefef;
}
.weekend::after{
content:'';
position:absolute;
height:100%;
width:25px;
top:1em;
z-index:-1;
background-color: #efefef;
}
<div id="mainPanel">
<div id="header">
<div class="headCell">1</div>
<div class="headCell">2</div>
<div class="headCell">3</div>
<div class="headCell">4</div>
<div class="headCell">5</div>
<div class="headCell weekend">6</div>
<div class="headCell weekend">7</div>
<div class="headCell">8</div>
<div class="headCell">9</div>
<div class="headCell">10</div>
<div class="headCell">11</div>
<div class="headCell">12</div>
<div class="headCell weekend">13</div>
<div class="headCell weekend">14</div>
<div class="headCell">15</div>
<div class="headCell">16</div>
<div class="headCell">17</div>
<div class="headCell">18</div>
<div class="headCell">19</div>
<div class="headCell weekend">20</div>
</div>
<div id="panelBody">
Here is some text that will appear in the main div. I am hoping to see this not moved around and that the grey weekend lines will appear underneath the text.
</div>
</div>
You can add an :after and set a width of 0 with a margin-left equal to the width of the cell (16px in this case.
This can be seen i the following:
#mainPanel {
overflow-x: scroll;
display: flex;
height: 100vh;
flex-direction: column;
}
#header {
height: 25px;
box-sizing: border-box;
display: flex;
flex-direction: row;
width: 100%;
}
.headCell {
height: 100%;
border: 1px #cccccc solid;
border-left: none;
box-sizing: border-box;
min-width: 25px;
display: flex;
align-items: center;
justify-content: center;
}
.weekend {
background-color: #efefef;
}
.weekend:after {
background-color: #efefef;
width: 20px;
height: 100vh; /* Adjust to suit */;
content: "";
display: inline-block;
margin-left: -16px;
z-index: -1;
}
<div id="mainPanel">
<div id="header">
<div class="headCell">1</div>
<div class="headCell">2</div>
<div class="headCell">3</div>
<div class="headCell">4</div>
<div class="headCell">5</div>
<div class="headCell weekend">6</div>
<div class="headCell weekend">7</div>
<div class="headCell">8</div>
<div class="headCell">9</div>
<div class="headCell">10</div>
<div class="headCell">11</div>
<div class="headCell">12</div>
<div class="headCell weekend">13</div>
<div class="headCell weekend">14</div>
<div class="headCell">15</div>
<div class="headCell">16</div>
<div class="headCell">17</div>
<div class="headCell">18</div>
<div class="headCell">19</div>
<div class="headCell weekend">20</div>
</div>
<div id="panelBody">
Here is some text that will appear in the main div. I am hoping to see this not moved around and that the grey weekend lines will appear underneath the text.
</div>
</div>
Picture describes it better, so I am attaching it.
So, this is simple list. Green areas are clickable and what I want to achieve is centering texts inside those green buttons, but those texts also should be aligned to left side. Not sure if I am being clear enough, but I do hope picture will explain the idea.
Tried to play with flex, but not successfully.
#container {
display: flex;
flex-direction: column;
align-items: center;
}
.item {
border: 1px solid red;
}
<div id="container">
<div id="otherContainer">
<div class="item">some text</div>
<div class="item">sone loooonger text</div>
<div class="item">text</div>
</div>
</div>
I expect to have some clean css which would allow me to have desired result as you can see in picture. So, question is, is it even possible to achieve without hackish css/JS solutions?
Yes, its possible to do this without javascript, but it comes with some limitations like having to set a max-width.
button {
display: block;
width: 100%;
border: none;
}
div {
margin: 1rem auto;
max-width: 100px;
text-align: left;
}
.bg-green {
background: green;
}
.bg-lightgreen {
background: lightgreen;
}
<button class="bg-green">
<div>Some text</div>
</button>
<button class="bg-lightgreen">
<div>Some other text</div>
</button>
<button class="bg-green">
<div>Text</div>
</button>
Here is a trick using table:
#container {
display: table;
width:100%;
}
.item {
background: yellow;
display:table-row;
white-space:nowrap;
}
.item:before,
.item:after{
content: "";
display:table-cell;
width:50%;
}
.item:hover {
background: red;
}
<div id="container">
<div class="item">some text</div>
<div class="item">sone loooonger text</div>
<div class="item">text</div>
</div>
I am trying to create tab module such as this:
https://codepen.io/oknoblich/pen/tfjFl
However I am having difficulty since I can not change the HTML layout:
<div class="container">
<div class="tab-header">Tab1</div>
<div class="tab-content teal">Content1</div>
</div>
<div class="container current">
<div class="tab-header">Tab2</div>
<div class="tab-content teal">Content2</div>
</div>
The problems are that absolute positioning removes the content from the document flow, while other methods prevents the content from being the full width of the page.
I created two codepen's that illustrates the difficulties:
https://codepen.io/dwigt/pen/pOQpLd (absolute positioning removes content from document flow)
https://codepen.io/dwigt/pen/YOREOJ (flexbox layout does not take up full page-width)
Is there anyway I can replicate the tab functionality using this HTML layout and no javascript?
You can use display: contents (which is unfortunately not too well supported) combined with flexbox layout with wrap, set on the .wrapper element. This way, tab-headers and tab-contents will be treated equally, as if they were at the same level with one another - the .container elements are "transparent" to the layout engine. As a result, they will all be laid out with flexbox logic applied. Finally, to have the three tab headers display first, we set the order of the tab contents to some high value (here 100), and since we have flex wrap enabled, the content is then pushed downwards to a new line, below the headers. See example below:
.wrapper {
max-width: 300px;
display: flex;
flex-wrap: wrap;
height: 100%;
}
.container {
height: 50px;
display: contents;
}
.container .tab-header {
width: 100px;
max-width: 100%;
max-height: 100%;
flex: 1 0 33.33%;
}
.container .tab-content {
display: none;
height: 200px;
order: 100;
}
.container.current .tab-content {
display: block;
width: 300px;
left: 0;
}
.footer {
height: 500px;
width: 300px;
display: block;
}
.red {
background: red;
}
.teal {
background: teal;
}
<div class="wrapper">
<div class="container">
<div class="tab-header">Tab1</div>
<div class="tab-content teal">Content1</div>
</div>
<div class="container current">
<div class="tab-header">Tab2</div>
<div class="tab-content teal">Content2</div>
</div>
<div class="container">
<div class="tab-header">Tab3</div>
<div class="tab-content teal">Content3</div>
</div>
</div>
<div class="footer red">Footer Text</div>
This isn't quite perfect because the first tab is a bit wider, but give this a shot and see if this doesn't get your closer to your goal. It allows your tabs to be 100% and also allows you to add more tabs that space evenly from edge to edge of your container.
Let me know how it works out :D
Add display: table-cell and width: 100% to your css selector label
label {
display: table-cell;
width: 100%;
margin: 0 0 -1px;
padding: 15px 25px;
font-weight: 600;
text-align: center;
color: #bbb;
border: 1px solid transparent;
}
I have been reading about BEM and I would like to start implementing it.
However, I am not very clear what would be the best approach. I have multiple flex divs with different styles, it really is very repetitive if I define each style in the class. But then will I end up using separate classes for each flex style?
This is a simplified example:
.cont {
border: 1px solid black;
margin: 10px;
display: flex;
padding: 50px
}
.cont--justify-start {
justify-content: flex-start;
}
.cont--direction-column {
flex-direction: column;
}
.cont--justify-center {
justify-content: center;
}
.cont--justify-end {
justify-content: flex-end;
}
.square {
width: 20px;
height: 20px;
}
.square--black {
background: black;
}
.square--blue {
background: blue;
}
.square--red {
background: red;
}
.square--green {
background: green;
}
<div class="cont cont--justify-center">
<div class="square square--black">
</div>
<div class="square square--blue">
</div>
</div>
<div class="cont cont--justify-start cont--direction-column">
<div class="square square--red">
</div>
<div class="square square--blue">
</div>
</div>
<div class="cont cont--justify-end">
<div class="square square--red">
</div>
<div class="square square--green">
</div>
</div>
This way one div might end up having 5-6 classes. What is the best way to do this?
Your code is perfectly valid!
<div class="cont cont--justify-start cont--direction-column">
You have to use the block or element name, followed by the modifier.
Please see the official documentation, they have added very nice examples. Some are even similar to your problem: https://en.bem.info/methodology/block-modification/
I got a problem with positioning, I need to show Element 2 before Element 1. It is because of a PHP traitement, php code of the second element is executed at the end but I need to show it in first in my page
Ex :
<div class="Element1">
Text after Element 2
</div>
<div class="Element2">
Text before Element 1
</div>
Wrap them in a container and you could make use of CSS3 Flexbox.
That way you only have to change the order. In fact just change the order on one div (Element2) and it will automatically switch. You could also use column-reverse to reverse the order of the entire list.
Something like this:
#container {
width: 240px; height: 240px;
border: 1px solid gray;
display: flex;
flex-direction: column;
/* flex-direction: column-reverse; */
/* use column-reverse if needed to reverse the entire list */
}
.Element1, .Element2 {
height: 100px;
margin: 8px;
}
.Element1 {
order: 2;
background-color: #00f;
}
.Element2 {
order: 1;
background-color: #f00;
}
<div id="container">
<div class="Element1">
Text after Element 2
</div>
<div class="Element2">
Text before Element 1
</div>
</div>