How to make div bigger and change it's content on hover? - javascript

I want a div to become bigger ("covering" area of other divs) and change it's content on hover.
Here is a code snippet showing how my page currently looks like:
.page__container {
display: grid;
grid-template-areas: "left-sidebar first-tile second-tile right-sidebar"
"left-sidebar third-tile fourth-tile right-sidebar";
grid-template-columns: 15% 35% 35% 15%;
}
.page__sidebar {
text-align: center;
background-color: black;
color: white;
}
.page__sidebar--left {
grid-area: left-sidebar;
}
.page__sidebar--right {
grid-area: right-sidebar;
}
.page__tile {
height: 100px;
line-height: 100px;
text-align: center;
vertical-align: middle;
}
.page__tile--first {
grid-area: first-tile;
background-color: white;
}
.page__tile--second {
grid-area: second-tile;
background-color: black;
color: white;
}
.page__tile--third {
grid-area: third-tile;
background-color: black;
color: white;
}
.page__tile--fourth {
grid-area: fourth-tile;
background-color: white;
}
<div class="page__container">
<aside class="page__sidebar page__sidebar--left">
<span>Sidebar</span>
</aside>
<div class="page__tile page__tile--first">
<span>Components</span>
</div>
<div class="page__tile page__tile--second">
<span>Peripherals</span>
</div>
<aside class="page__sidebar page__sidebar--right">
<span>Sidebar</span>
</aside>
<div class="page__tile page__tile--third">
<span>Laptops</span>
</div>
<div class="page__tile page__tile--fourth">
<span>Accessories</span>
</div>
</div>
This is how I want it to look like when I hover over the first tile (components).
I don't know whether it is possible to do using grids or no so I am open to various suggestions about potential changes in my code.

I would recommend using JavaScript for this. You can't possibly use grids, grids are useful only for layouts. The closest thing we have to a parent selector in CSS is :focus-within pseudo element.
:focus-within

For changing the size, you can use scale command in CSS; more here.You could also use the z-index command in order to a div appear in front of other. However, I think that this kind of animation is a lot better to do using javascript. There are a lot of tutorials on youtube that cover javascript animations like this.

Related

Can I apply CSS to a flex-item when it wraps onto a new row?

.wrapper {
border: 5px solid pink;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.a-fc {
background-color: purple;
width: 300px;
/*height: 100px;*/
}
.b-fc {
background-color: orange;
display: flex;
flex-direction: column;
/*flex-wrap: wrap;*/
flex-basis:70px;
flex-grow:1;
}
.b-fc > * {
flex-grow: 1;
flex-basis: 100px;
}
.b-fc > *:nth-child(1) {
background-color: red;
}
.b-fc > *:nth-child(2) {
background-color: blue;
}
.b-fc > *:nth-child(3) {
background-color: green;
}
<div class="wrapper">
<div class="a-fc">
<div>a1</div>
</div>
<div class="b-fc">
<div>b1</div><div>b2</div><div>b3</div>
</div>
</div>
FC = flex-container.
FI = flex-item.
I am able to place .b-fc onto a new row when the space left for it to exist on the original row goes below 70px.
My task: I want b-fc's FIs to stack vertically when no new row is created/they don't wrap. I want b-fc's FIs to align horizontally when b-fc wraps.
Current solution
In the code-snippet above, I've tried to achieve my task by writing one set of properties that work for both scenarios by setting a `flex-basis` on `.b-fc`'s FIs. If the space left for `.b-fc`'s FIs is less than this flex-basis (100px), the FIs will stack vertically. The weakness: i) if `.b-fc`'s `width`'s larger than 300px, its FIs align horizontally ii) When `.b-fc` wraps, its FIs wrap when `.bf-c` is less than 300px.
Therefore, I'm figuring it'd be more powerful to be able to apply CSS when .b-fc wraps. Is this possible?
*Idea 1: CSS variables & JS*
Perhaps using CSS variables/SASS I could continually assess whether FC - .a-fc <= than 70px. If true, apply stylings to .b-fc.
Idea 2: media-queries
Another option is to test when row2 is made, use media queries to capture this and apply CSS to .b-fc with media queries.
P.S. Similar question has been asked here before in 2015. Maybe new techniques have transpired since.
For this particular case you can consider the use of max() combined with flex-basis. The trick is to either have 0px (horizontal item) or a very big value (vertical items).
You will note that this is not a generic solution and the value is based on your html structure:
395px = 300px (width of a-fx) + 70px (flex-basis of b-fc) + 10px (border of wrapper) + 16px (default body margin) - 1px
.wrapper {
border: 5px solid pink;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.a-fc {
background-color: purple;
width: 300px;
}
.b-fc {
background-color: orange;
display: flex;
flex-wrap: wrap;
flex-basis: 70px;
flex-grow: 1;
}
.b-fc>* {
flex-grow: 1;
flex-basis: max(0px, (100vw - 395px)*100);
height: 100px;
}
.b-fc>*:nth-child(1) {
background-color: red;
}
.b-fc>*:nth-child(2) {
background-color: blue;
}
.b-fc>*:nth-child(3) {
background-color: green;
}
<div class="wrapper">
<div class="a-fc">
<div>a1</div>
</div>
<div class="b-fc">
<div>b1</div>
<div>b2</div>
<div>b3</div>
</div>
</div>
So to answer your question: No, we cannot apply CSS on wrapping (CSS cannot detect wrapping) but we can always find workaround of each case.
Similar questions:
Without media queries how to achieve 3 column desktop to 1 column mobile layout
CSS grid maximum number of columns without media queries

How to make one div always be at the bottom of the view and make top div resize based on bottom div?

I'm pretty new to web development and I'm working on something which requires two divs to always take up 100% of the viewport.
I have div A which is an interactive image that should be as big as possible and should take up the top part of the screen.
Then div B which contains either 1 or 2 buttons depending on what action is done on the interactive div A. Div B is at the bottom of the view.
Is there a clean way to make the size of A depend on the size that div B takes up dynamically? Like just the "remainder" of the viewport should be div A. I put an image below of what I'm attempting to achieve. The second image shows what would happen if some action is done in div A - for simplicity, we could say if some method potato() is called, we want div B to now contain two buttons.
I have tried doing a solution with:
position: fixed;
bottom: 0;
and Div B looks 90% right that way, but it doesn't resize Div A and I also don't want Div B "covering" anything in this way. I just want it to be the same level as Div A and sharing the space to get 100% of the viewport.
Any help would be greatly appreciated! I'd prefer to use plain CSS if possible. I'm doing some away team work and can't add much in the way of libraries or new dependencies to the project.
check on this fiddle https://jsfiddle.net/kt931frp/1/ the trick is using flex as suggested by the below answer.
<div class="wrapper">
<div class="part1"></div>
<div class="part2">
<div contenteditable="true"class="contenteditable">continue typing...</div>
</div>
</div>
body {
margin: 0;
}
.wrapper {
height: 100vh;
display: flex;
flex-direction: column;
}
.part1 {
background:#ffff00;
flex: 1 0 auto;
}
.part2 {
padding: 2em;
color: white;
background:#ff0000;
}
.contenteditable{
width:100%;
min-height:50px;
}
Actually, this is pretty easy using Flexbox and the flex property.
You can change the padding value to see how the top block reacts.
body {
margin: 0;
}
main {
height: 100vh;
display: flex;
flex-direction: column;
}
.top-part {
flex: 1 0 auto; /* This tells `top-part` to take the remaining place. */
background: violet;
}
.bottom-part {
padding: 2em;
color: white;
background: lightblue;
}
<main>
<section class="top-part"></section>
<section class="bottom-part">
Some text here
</section>
</main>
Bringing my 2 cents, you can also take advantage of display: table|table-row|table-cell to create this layout (see the MDN documentation on display property to know more).
The trick when using these properties, unless display: flex, is to tell the "actions" cell to measure 0.1px, which will force the cell to be the minimum possible. However, it does not crushes its inner content, allowing to dynamically adjust depending the content inside.
As cells are by default sharing spaces, this does the job for this kind of layout because the "Div A" is using the rest of the available space.
Check this JSFiddle or use the snippet code below to play with it. I annoted the properties you can tweak.
body {
margin: 0px;
}
.app {
width: 100vw;
height: 100vh;
display: table;
}
.main,
.actions {
display: table-row;
}
.main > div,
.actions > div {
display: table-cell;
vertical-align: middle;
text-align: center;
border-width: 10px; /* tweak this */
border-style: solid; /* tweak this */
}
.main > div {
border-color: purple; /* tweak this */
background-color: violet; /* tweak this */
}
.actions > div {
padding: 20px; /* tweak this */
border-color: blue; /* tweak this */
background-color: lightblue; /* tweak this */
height: 0.1px;
}
.button {
width: 200px; /* tweak this */
padding: 10px; /* tweak this */
}
<div class="app">
<main class="main">
<div>
Div A
</div>
</main>
<footer class="actions">
<div>
<div>
Div B - some text and 2 buttons
</div>
<div>
<button class="button">
Button 1
</button>
</div>
<div>
<button class="button">
Button 2
</button>
</div>
</div>
</footer>
</div>
Hope it help you getting inspiration.

How do I properly embed Cesium inside grid element

I'm attempting to control my Cesium container element with CSS Grid. But in Edge it seems to automatically zoom past the Earth if it is within the grid. It does not seem to happen if I use Chrome or even IE. What exactly is happening and how should I combat it? Basic code being used below. Can use https://codepen.io/rachelandrew/pen/XdZydB to plug it in:
CSS:
body {
margin: 40px;
}
.wrapper {
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(auto-fill, [col] 100% ) ;
grid-template-rows: repeat(auto-fill, [row] auto );
background-color: #fff;
color: #444;
}
.box {
background-color: #444;
color: #fff;
border-radius: 5px;
padding: 20px;
font-size: 150%;
}
.a {
grid-column: col / span 2;
grid-row: row ;
}
HTML:
<div class="wrapper">
<div id="cesiumContainer" class="box a">A</div>
</div>
<script src="https://cesiumjs.org/releases/1.55/Build/Cesium/Cesium.js"></script>
<link href="https://cesiumjs.org/releases/1.55/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
JS:
var viewer = new Cesium.Viewer('cesiumContainer');
EDIT: I did not notice at first, but I had overflow set to hidden. Removing that reveals that Edge seems to forever increase the element resize when using Cesium. I think it has something to do with
grid-template-columns: repeat(auto-fill, [col] 100% ) ;
EDIT 2: I ended up ditching the grid for my Cesium-related work. I never found a solution using the grid technology. Instead, I've implemented flex groups which don't seem to affect the rendering in the same way. I did keep a copy of my other framework in the hopes that I'll stumble on a solution, if I do I'll post an official answer unless someone beats me to it.

How do I change the color of the text when it is in the photo?

There is a block with a photo and a specific title. When scrolling, this text changes its position (transform: translate3d). It is necessary to change the color of the symbols when they are on the photo.
Perhaps someone has come across such a situation and can help in this? I have attached a photo for a better understanding of the task
If you want a pure CSS solution, you can use mix-blend-mode. Note what browsers it is available in though.
It will decide how content from one element should blend with the content of the element's direct parent.
:root {
--main-color: white;
--secondary-color: black;
}
#app {
width: 100vw;
height: 100vh;
background: repeating-linear-gradient(-45deg, var(--main-color), var(--main-color) 30px, var(--secondary-color) 30px, var(--secondary-color) 60px);
display: flex;
align-items: center;
justify-content: center;
}
.blend {
font-family: sans-serif;
font-size: 2em;
color: white;
mix-blend-mode: difference;
}
<div id="app">
<div class="blend">Hello world, how are you?</div>
</div>

CSS: Set divs horizontally in 2 rows

Lets say I have
<div class="cont">
<div class="single">1</div>
<div class="single">2</div>
<div class="single">3</div>
<div class="single">4</div>
<div class="single">5</div>
<div class="single">6</div>
<div class="single">7</div>
</div>
What I want to have is to plase the .single divs in 2 rows like bricks horizontaly from left to right this simple way: 1st div will be in left top corner, 2nd will be placed below 1st, 3rd will be placed next to 1st, 4th will be placed below 3rd and so on like:
1 3 5 7 9
2 4 6 8
All the divs has the same size.
I've tried with masonry.js and its working like a charm, but its way to complex solution for so simple task (simply solution is important).
fiddle playground
There is a CSS property that does exactly that
http://tinker.io/8ff59
.cont {
-webkit-columns: 5em;
-moz-columns: 5em;
columns: 5em; /* desired width of column */
}
http://caniuse.com/#feat=multicolumn
I had the very same problem and solved using the grid.
Here's the CSS you should add to your container:
.cont {
height: 220px;
background: red;
display: grid;
grid-template-rows: repeat(2, 100px);
gap: 10px;
grid-auto-flow: column;
grid-auto-columns: 100px;
}
I don't think you can do that with css with structure as you have.
This structure should help you to get your required layout:
<div class="a">
<div class="b">
<div class="c">1</div>
<div class="c">2</div>
</div>
<div class="b">
<div class="c">3</div>
<div class="c">4</div>
</div>
</div>
<style>
div.a div.b {float: left; width: 100px;}
</style>
For the sake of argument, let's say you can't change your document structure - you need to do this through layout definitions alone.
If you know how many items you will have, the easiest way to manage this would be CSS3 columns with inline-block elements. Your .singles are the inline-blocks, and .cont uses the 'columns' property to set 5 columns each wide enough to hold your singlets, whilst using max-height to force the inline-blocks onto new columns every two items. The singlets have a min-size large enough to stop multiple inline-blocks displaying on the same line.
You can see this effect as a jsfiddle here: http://jsfiddle.net/mwjJG/25/ :
.container {
height: 240px;
columns: 100px 5;
-webkit-columns: 100px 5;
-moz-columns: 100px 5;
}
.single {
display: inline-block;
height: 100px;
width: 100px;
}
Do be aware this won't work on IE<10 unless you can use some kind of JS-based shiv to add support for the columns property (CSS Pie may be able to do this).
I accomplished this with CSS here using this code: It's kind of hackish though.
I set three of the divs (the last three) to the class 'double'
.cont .single {
background: blue;
color: white;
width: 100px;
height: 100px;
margin: 10px;
float:left;
display: inline-block;
}
.cont .double {
background: blue;
color: white;
width: 100px;
height: 100px;
margin: 10px;
display:inline-block;
float:left;
}
div:nth-child(5) {
clear:left;
}
.cont {
height: 220px;
background: red;
}

Categories