I have a two row grid with three columns. Each row has a text in the middle column. The first row's middle column needs to fit to the text. But when there is a longer text in the second row, the first row's middle column won't fit to the text. A better explanation with pictures above:
When the first row's text is longer then it fits correctly.
But when the second row's text is longer than the first row's text, the first row's column won't fit the text.
How can I fit the first row middle column's width to the text?
Here is
html,
body,
.grid-container {
height: 100%;
margin: 0;
}
.grid-container {
justify-content: center;
display: grid;
grid-template-columns: 10vmin min-content 10vmin;
grid-template-rows: 1fr 1fr 1fr;
gap: 0px 0px;
grid-template-areas: "left middle right ""left first-text-middle right""second-text-left second-text-middle second-text-right";
}
.left {
border: 1px solid red;
grid-area: left;
text-align: right;
}
.right {
border: 1px solid red;
grid-area: right;
}
.middle {
border: 1px solid red;
grid-area: middle;
}
.second-text-left {
border: 1px solid red;
grid-area: second-text-left;
}
.second-text-right {
border: 1px solid red;
grid-area: second-text-right;
}
.first-text-middle {
border: 1px solid red;
text-align: center;
grid-area: first-text-middle;
align-self: stretch;
vertical-align: top;
}
.second-text-middle {
border: 1px solid red;
text-align: center;
grid-area: second-text-middle;
align-self: stretch;
vertical-align: top;
}
<div class="grid-container">
<div class="left"></div>
<div class="middle"></div>
<div class="right"></div>
<div class="left"></div>
<div class="first-text-middle">
<span id="n1">LoremIps</span>
</div>
<div class="second-text-left "></div>
<div class="second-text-middle">
<span id="n3">Lorem</span>
</div>
<div class="second-text-right"></div>
</div>
If you want the top text to expand according to the width of the parent element (which has been expanded by the .second-text-middle inner text), you could use simple JavaScript.
Here we can check the width of #n1 and .first-text-middle, and increase the font size: n%; of #n1 until it fits the parent.
fitWidth();
window.addEventListener("resize", function() {
fitWidth();
});
function fitWidth() {
let first = document.querySelector('.first-text-middle');
let firstText = document.getElementById('n1');
let textSize = 100; // we will use it like a base 100% font-size later
// set font size to '#n1'
firstText.style.cssText = 'font-size:' + textSize + '%';
while (first.clientWidth - 2 >= firstText.offsetWidth) {
textSize = textSize + 1; //increments font size by 1% each loop
firstText.style.cssText = 'font-size:' + textSize + '%';
// basically in DOM you see only result of the very last loop of this 'while' statment
}
}
html,
body,
.grid-container {
height: 100%;
margin: 0;
}
.grid-container {
justify-content: center;
display: grid;
grid-template-columns: 10vmin min-content 10vmin;
grid-template-rows: 1fr 1fr 1fr;
gap: 0px 0px;
grid-template-areas: "left middle right ""left first-text-middle right""second-text-left second-text-middle second-text-right";
}
.left {
border: 1px solid red;
grid-area: left;
text-align: right;
}
.right {
border: 1px solid red;
grid-area: right;
}
.middle {
border: 1px solid red;
grid-area: middle;
}
.second-text-left {
border: 1px solid red;
grid-area: second-text-left;
}
.second-text-right {
border: 1px solid red;
grid-area: second-text-right;
}
.first-text-middle {
border: 1px solid red;
text-align: center;
grid-area: first-text-middle;
align-self: stretch;
vertical-align: top;
}
.second-text-middle {
border: 1px solid red;
text-align: center;
grid-area: second-text-middle;
align-self: stretch;
vertical-align: top;
overflow: hidden;
}
<div class="grid-container">
<div class="left"></div>
<div class="middle"></div>
<div class="right"></div>
<div class="left"></div>
<div class="first-text-middle">
<span id="n1">Lorem</span>
</div>
<div class="second-text-left "></div>
<div class="second-text-middle">
<span id="n3">LoremIps</span>
</div>
<div class="second-text-right"></div>
</div>
Related
How to create 3 divs side by side using flex where middle div can (grow&shrink) in respect to other two divs?
I want to create Three divs A B C with a parent containing flex css property. Having A fixed width of 300px and C having min width 200px and can grow in width as more content is added.
While B should be in between A and C should grow and shrink automatically as per the widths of A and C.
Although A and C can be of any width 300px and 200px are just examples.
I've tried but unable to place it correctly.
For C i used flex: 1 1 0%; with A and C with fixed width - But didn't worked
You can give childB, You can read more about flex here
flex: 1;
.parent {
display: flex;
}
.child {
height: 300px;
display: flex;
justify-content: center;
align-items: center;
}
.childA {
flex-basis: 300px;
background-color: turquoise;
}
.childB {
flex: 1;
background-color: wheat;
}
.childC {
flex-basis: 200px;
background-color: blueviolet;
}
<div class="parent">
<div class="child childA">A</div>
<div class="child childB">B</div>
<div class="child childC">C</div>
</div>
it will be easier if you write your own code, which does not work
.abc {
display: flex;
height: 200px;
width: 400px;
margin: 0 auto;
border: 1px solid black;
}
.A {
min-width: 150px;
flex-shrink: 0;
background-color: aliceblue;
}
.B {
flex-grow: 1;
background-color: grey;
}
.C {
min-width: 100px;
flex-shrink: 0;
background-color: antiquewhite;
}
<div class="abc">
<div class="A"></div>
<div class="B"></div>
<div class="C"></div>
</div>
HTML :
<div class="container">
<div class="box">A</div>
<div class="box">B</div>
<div class="box">C</div>
</div>
CSS :
.container {
display: flex;
flex-wrap: nowrap;
border: 1px solid red;
height: 100px;
}
.box {
border: 1px solid black;
margin: 5px 5px 5px 5px;
}
.box:nth-child(2) {
width:25%;
background-color: blue;
}
you can use nth-child(child) to select any child and costom it
Result : https://codepen.io/pk-salma/pen/qBjqwBG
I'm running into an error with a javascript code I'm working on. I'm trying to make a collapsible sidebar. Whenever the user is hovering over the bar, the sidebar should be 280px wide and the main content should be calc(100vw-280px). Alternatively, whenever the user is NOT hovering over the bar, the sidebar should be 80px wide and the main content should be calc(100vw-80px).
This seems simple enough, but the #content div is not resizing whenever the function runs. The only thing I can figure is that javascript does not play friendly with calc but there could be something else I'm overlooking too in the CSS or with default values. I'm including all of the code just to be safe. Any help is appreciated!!
var mini = true;
function toggleSidebar() {
if (mini) {
document.getElementById("rightbar").style.width = "280px";
document.getElementById("content").style.width = "calc(100vw-280px)";
this.mini = false;
} else {
document.getElementById("rightbar").style.width = "80px";
document.getElementById("content").style.width = "calc(100vw-80px)";
this.mini = true;
}
}
body {margin: 0; background-color: #F2F2F2;}
.topbar {
z-index: 10;
position: fixed;
top: 0; left: 0;
width: 100vw; height: 56px;
font-size: x-large;
background-color: #5B7042;
border-bottom: 4px solid #3F5328}
#rightbar {
z-index: 1;
position: fixed;
top: 60px; right: 0%;
width: 80px; height: calc(100vh - 60px);
overflow-y: auto;
overflow-x: hidden;
transition: 0.5s;
color: #412A1B;
border-left: 2px solid darkgray}
#content {
display: grid;
position: fixed;
top: 60px; left: 0;
width: calc(100vw - 80px);
height: calc(100vh - 60px);
padding: 32px;
box-sizing: border-box;
grid-auto-columns: 1fr;
grid-template-columns: 1fr 300px;
grid-template-rows: 1fr 1fr 1fr 1fr;
gap: 20px 40px;
grid-template-areas:
"hello hello"
"announce tasks"
"announce tasks"
"announce streak";}
.hello {
grid-area: hello;
margin-top: 20px;
margin-bottom: 30px;
text-align: center;
font-size: 3em;
color: #3F5328}
.announce {
overflow: scroll;
grid-area: announce}
.tasks {
padding: 20px;
grid-area: tasks;
text-align: center;}
.something {grid-area: something}
.streak {
grid-area: streak;
font-size: 52px;
font-weight: 800}
.module {
background-color: white;
border-radius: 6px;
box-shadow: 3px 4px #CECECE}
table {width: 100%}
td {
padding: 10px 20px;
border-bottom: 1px solid lightgray;}
td .msg {
font-size: 20px;
line-height: 1.5}
.posted {
display: grid;
grid-template-columns: 42px 2fr 1fr;
grid-template-areas:
"pic author timestamp"}
.posted .img {grid-area: pic}
.posted .author {
grid-area: author;
display: flex;
align-items: center;
font-weight: 800;
font-size: 16px;}
.posted .timestamp {
grid-area: timestamp;
display: flex;
justify-content: flex-end;
align-items: center;
color: gray;
font-size: 16px}
.pic{
width: 25px;
clip-path: circle();}
<link rel='stylesheet' href='https://classcolonies.com/resources/style.css'>
<div class='topbar'></div>
<div id='rightbar' onmouseover="toggleSidebar()" onmouseout="toggleSidebar()"></div>
<div id='content'>
<div class='hello'>Hi, John.</div>
<div class='module tasks center'><p>You have <b>10 tasks</b> to do this week.</p></div>
<div class='module streak center'>🔥 32</div>
<div class='module announce'>
<table>
<tr>
<td>
<span class='msg'>Please do not message me at the moment. I am trying to fix this horrible CSS glitch..</span>
<div class='posted'>
<span class='img'><img class='pic' src='https://mrdansby.com/resources/pics/1.png'></span>
<span class='author'>Mr. Dansby</span>
<span class='timestamp'>33m ago</span>
</div>
</td>
</tr>
<tr>
<td>
<span class='msg'>Have a great fall break!</span>
<div class='posted'>
<img class='pic' src='https://mrdansby.com/resources/pics/1.png'>
<span class='author'>Mr. Dansby</span>
<span class='timestamp'>1d ago</span>
</div>
</td>
</tr>
<tr>
<td>
<span class='msg'>Be sure to bring a pencil and paper to class tomorrow!</span>
<div class='posted'>
<img class='pic' src='https://mrdansby.com/resources/pics/1.png'>
<span class='author'>Mr. Dansby</span>
<span class='timestamp'>3d ago</span>
</div>
</td>
</tr>
</table>
</div>
</div>
calc is a bit persnickety about whitespace.. Specifically, the operator in the calc equation must have a space on either side. I updated your calc JS setting lines from something like this...
document.getElementById("content").style.width = "calc(100vw-280px)";
...to include the whitespace:
document.getElementById("content").style.width = "calc(100vw - 280px)";
...and it seems closer to what I think you're looking for; see the snippet below:
var mini = true;
function toggleSidebar() {
if (mini) {
document.getElementById("rightbar").style.width = "280px";
document.getElementById("content").style.width = "calc(100vw - 280px)";
this.mini = false;
} else {
document.getElementById("rightbar").style.width = "80px";
document.getElementById("content").style.width = "calc(100vw - 80px)";
this.mini = true;
}
}
body {margin: 0; background-color: #F2F2F2;}
.topbar {
z-index: 10;
position: fixed;
top: 0; left: 0;
width: 100vw; height: 56px;
font-size: x-large;
background-color: #5B7042;
border-bottom: 4px solid #3F5328}
#rightbar {
z-index: 1;
position: fixed;
top: 60px; right: 0%;
width: 80px; height: calc(100vh - 60px);
overflow-y: auto;
overflow-x: hidden;
transition: 0.5s;
color: #412A1B;
border-left: 2px solid darkgray}
#content {
display: grid;
position: fixed;
top: 60px; left: 0;
width: calc(100vw - 80px);
height: calc(100vh - 60px);
padding: 32px;
box-sizing: border-box;
grid-auto-columns: 1fr;
grid-template-columns: 1fr 300px;
grid-template-rows: 1fr 1fr 1fr 1fr;
gap: 20px 40px;
grid-template-areas:
"hello hello"
"announce tasks"
"announce tasks"
"announce streak";}
.hello {
grid-area: hello;
margin-top: 20px;
margin-bottom: 30px;
text-align: center;
font-size: 3em;
color: #3F5328}
.announce {
overflow: scroll;
grid-area: announce}
.tasks {
padding: 20px;
grid-area: tasks;
text-align: center;}
.something {grid-area: something}
.streak {
grid-area: streak;
font-size: 52px;
font-weight: 800}
.module {
background-color: white;
border-radius: 6px;
box-shadow: 3px 4px #CECECE}
table {width: 100%}
td {
padding: 10px 20px;
border-bottom: 1px solid lightgray;}
td .msg {
font-size: 20px;
line-height: 1.5}
.posted {
display: grid;
grid-template-columns: 42px 2fr 1fr;
grid-template-areas:
"pic author timestamp"}
.posted .img {grid-area: pic}
.posted .author {
grid-area: author;
display: flex;
align-items: center;
font-weight: 800;
font-size: 16px;}
.posted .timestamp {
grid-area: timestamp;
display: flex;
justify-content: flex-end;
align-items: center;
color: gray;
font-size: 16px}
.pic{
width: 25px;
clip-path: circle();}
<link rel='stylesheet' href='https://classcolonies.com/resources/style.css'>
<div class='topbar'></div>
<div id='rightbar' onmouseover="toggleSidebar()" onmouseout="toggleSidebar()"></div>
<div id='content'>
<div class='hello'>Hi, John.</div>
<div class='module tasks center'><p>You have <b>10 tasks</b> to do this week.</p></div>
<div class='module streak center'>🔥 32</div>
<div class='module announce'>
<table>
<tr>
<td>
<span class='msg'>Please do not message me at the moment. I am trying to fix this horrible CSS glitch..</span>
<div class='posted'>
<span class='img'><img class='pic' src='https://mrdansby.com/resources/pics/1.png'></span>
<span class='author'>Mr. Dansby</span>
<span class='timestamp'>33m ago</span>
</div>
</td>
</tr>
<tr>
<td>
<span class='msg'>Have a great fall break!</span>
<div class='posted'>
<img class='pic' src='https://mrdansby.com/resources/pics/1.png'>
<span class='author'>Mr. Dansby</span>
<span class='timestamp'>1d ago</span>
</div>
</td>
</tr>
<tr>
<td>
<span class='msg'>Be sure to bring a pencil and paper to class tomorrow!</span>
<div class='posted'>
<img class='pic' src='https://mrdansby.com/resources/pics/1.png'>
<span class='author'>Mr. Dansby</span>
<span class='timestamp'>3d ago</span>
</div>
</td>
</tr>
</table>
</div>
</div>
I make a game for a project that you must find the real neighbours of a country.
I have this HTML code:
.game-panel {
gap: 10px;
display: grid;
grid-template-columns: 200px auto;
grid-template-rows: 5.5em 22px auto;
gap: 10px;
grid-template-areas: "side main" "side main2" "side main3";
}
#sidebar {
width: 200px;
border-radius: 5px;
background-color: #ff1493;
display: flex;
grid-area: side;
flex-direction: column;
z-index: 100;
}
#playing-country {
display: flex;
border-radius: 5px;
background-color: #708090;
grid-area: main;
}
#progress {
-webkit-appearance: none;
display: flex;
position: sticky;
top: 0;
height: 24px;
grid-area: main2;
height: 24px;
border: 1px solid #ccc;
color: #aaa;
width: 100%;
border-radius: 5px;
z-index: 102;
}
#progress[value]::-webkit-progress-bar {
background: #f1f1f1;
}
#progress[value]::-webkit-progress-value {
background: blue;
}
#neighbours-panel {
border-radius: 5px;
grid-area: main3;
display: flex;
flex-shrink: 1;
background-color: #fff;
}
.overlay {
position: absolute;
padding: 0 !important;
margin: 0 !important;
background-color: rgba(136, 132, 132, 0.5);
}
<div class="game-panel">
<div id='sidebar'>
<h3>Βρες τους γείτονες</h3>
<div id="round">Γύρος: <span id='round-text'>0</span></div>
<div id="score">Σκορ: <span id='score-text'>0</span></div>
<button id="btn-next-round"><span>Επόμενη χώρα</span></button>
<button id="btn-new-game"><span>Νέο παιχνίδι</span></button>
</div>
<div id="playing-country">playing-country</div>
<progress id='progress' max='100' value='0'></progress>
<div id='neighbours-panel'>
</div>
</div>
In the #neighbours-panel I dynamically create divs with country choices and when I click the right ones, a semi-transparent div with overlay class is created inside the #neighbours-panel that covers only the #neighbours-panel with the countries. To do this I add position:relative; to the parent #neighbours-panel and position:absolute; to the newly created overlay div. The #progress must be sticky on the top of the page when scroll down. The problem is that with position:relative; on the #neighbours-panel in order to work properly the overlay, the position:sticky; of the #progress is disabled. If I remove position:relative; then the sticky position works as it should but then the overlay div covers the whole page and not only the #neighbours-panel as it should. Can anyone help me find out what to do?
I want to align two images and a DIV. The DIV thats a rounded box keeps ending up beneath the two images.
Here's my HTML/CSS:
.main {
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 600px;
height: 110px;
}
.one {
float: right;
height: 100px;
}
.two {
height: 100px;
}
.box {
position: absolute;
height: 50px;
width: 50px;
}
.rounded {
border-radius: 10px;
border-color: #FFF;
border: 5px solid white;
}
<div id="main" class="main">
<div id="one" class="one">
</div>
<div id="two" class="two"><img src="[![apple][1]][1]" width="100" height="76" /> <img src="[![titleofpage][1]][1]" width="309" height="61" />
<div class="box rounded"></div>
</div>
</div>
How can I align them all in a straight line in this centered DIV in the middle of the page?
You can try out flexbox:
.flex-container-center {
display: flex;
align-items: center; /* this is what you need :) */
justify-content: center;
}
<div class="flex-container-center">
<img src="https://via.placeholder.com/200x200" />
<img src="https://via.placeholder.com/100x100" />
<img src="https://via.placeholder.com/200x50" />
</div>
Also, here's a working example and my favorite guide on flexbox :)
Add display: flex and justify-content: center to .two class;
.two {
display: flex;
justify-content: center;
height: 100px;
}
When using display: flex, there is a main-axis and cross-axis and you can set the main axis with flex-direction: row or flex-direction: column. The default is flex-direction: row without calling it. This means in the above example the main-axis = row and cross-axis = column.
When centering items using flex box you have two options:
align-items: center
justify-content: center
align-items controls the cross axis and justify-content controls the main axis.
In your example the main axis is row because the flex-direction wasn't called, so it used the default row. To center the items on the horizontal axis, you have to use justify-content, which uses the main axis (flex-direction) --> row
I tweaked the CSS to use grid view, removed the absolute positions and floats. Added borders so I could see things :)
.main{
position: block;
margin: 0 auto;
width: 600px;
height: 110px;
}
.one {
border: 5px solid blue;
height: 100px;
}
.two {
display: grid;
grid-template-columns: repeat(3, 30%);
height: 100px;
border: 5px solid yellow;
}
.box {
height:50px;
width:50px;
}
.rounded {
border-radius: 10px;
border-color:#FFF;
border: 5px solid red;
}
Please take a look at the below example. I'm learning css grids. The whole purpose is to keep things simple and to not need to specify distinct layout details on the child elements unnecessarily, so solutions should conform to this pattern.
Given the following:
function toggle(t) {
document.querySelectorAll('div').forEach(el =>
el.classList[0] === t.classList[0] ?
el.classList.toggle('selected') :
el.classList.remove('selected'))
}
:root,
html,
body,
main {
margin: 0;
padding: 0;
font-family: sans-serif;
height: 100%;
}
main {
border: solid 3pt white;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr 1fr;
}
div {
grid-area: span 2 / span 2;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
font-size: 5em;
font-weight: bold;
color: white;
background: grey;
}
.one {
background: red
}
.two {
background: green
}
.three {
background: blue
}
.selected {
width: 150%;
height: 150%;
z-index: 2;
}
<main>
<div class=one onclick="toggle(event.target)">one</div>
<div class=two onclick="toggle(event.target)">two</div>
<div class=three onclick="toggle(event.target)">three</div>
<div class=four onclick="toggle(event.target)">four</div>
</main>
https://jsfiddle.net/robbie_at_harvard/a3ouq711/1/
Please adjust to cause the areas two, three and four to expand towards the middle instead of always from the top-left corner? Again, preferably with generic rules rather than ones specific to the div.class specifications.
Second question, if I wanted instead a 4x4 layout of 2x2 child elements, where clicking on one element expanded it to 3x3 and contracted the others to 1x2, 2x1, and 1x1 in the opposite corner, what is necessary to produce this solution?
You could use transform:scale(1.5) and position it with transform-origin.
It would require specific CSS rules depending on the grid (i use :nth-child to target each element)
For 2x2 use
main div:nth-child(1){transform-origin: top left;}
main div:nth-child(2){transform-origin: top right;}
main div:nth-child(3){transform-origin: bottom left;}
main div:nth-child(4){transform-origin: bottom right;}
.selected {
transform:scale(1.5);
z-index: 2;
}
function toggle(t) {
document.querySelectorAll('div').forEach(el =>
el.classList[0] === t.classList[0] ?
el.classList.toggle('selected') :
el.classList.remove('selected'))
}
:root,
html,
body,
main {
margin: 0;
padding: 0;
font-family: sans-serif;
height: 100%;
}
main {
border: solid 3pt white;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr 1fr;
}
div {
grid-area: span 2 / span 2;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
font-size: 5em;
font-weight: bold;
color: white;
background: grey;
}
.one {
background: red
}
.two {
background: green
}
.three {
background: blue
}
main div:nth-child(1) {
transform-origin: top left;
}
main div:nth-child(2) {
transform-origin: top right;
}
main div:nth-child(3) {
transform-origin: bottom left;
}
main div:nth-child(4) {
transform-origin: bottom right;
}
.selected {
transform: scale(1.5);
z-index: 2;
}
<main>
<div class=one onclick="toggle(event.target)">one</div>
<div class=two onclick="toggle(event.target)">two</div>
<div class=three onclick="toggle(event.target)">three</div>
<div class=four onclick="toggle(event.target)">four</div>
</main>
I think it's difficult to have a general solution since the 4 blocks need to move in different ways. By the way here a solution that involve few CSS changes.
I know you want a generic one but i think in all the cases you will have some specificities (like the color and the content)
function toggle(t) {
document.querySelectorAll('div').forEach(el =>
el.classList[0] === t.classList[0] ?
el.classList.toggle('selected') :
el.classList.remove('selected'))
}
:root,
html,
body,
main {
margin: 0;
padding: 0;
font-family: sans-serif;
height: 100%;
}
main {
position:relative;
border: solid 3pt white;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr 1fr;
}
div {
grid-area: span 2 / span 2;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
font-size: 5em;
font-weight: bold;
color: white;
background: grey;
transition:0.5s;
}
.one {
background: red;
}
.two {
background: green;
right:25%;
}
.three {
background: blue;
bottom:25%;
}
.four {
bottom:25%;
right:25%;
}
.selected {
position:relative;
width:150%;
height:150%;
}
<main>
<div class=one onclick="toggle(event.target)">one</div>
<div class=two onclick="toggle(event.target)">two</div>
<div class=three onclick="toggle(event.target)">three</div>
<div class=four onclick="toggle(event.target)">four</div>
</main>