Why is the Grid Container selection only showing the first column? - css

I know enough CSS to be dangerous but not productive. I just learned about grids.
In my image below, you'll see I have a 2 column grid set up. The left column contains a "project name". This is an li tag. The right column contains a settings gear icon. This is a span tag. These are both children of a parent div
I set the grid up on the parent div, which I have rolled over in the image below. Why is the grid container size only the size of the first column and not the whole row?
This is causing me confusion because I want to have a border across the whole row when I rollover the row.
My HTML (JSX):
<div className={styles.project}>
<li onClick={() => props.onSelect(props.name)}>{props.name}</li>
<span className={styles.settings}>{"\u2699"}</span>
</div>
My CSS:
.project {
font-family: "Rubik", sans-serif;
grid-template-areas: "name settings";
grid-template-columns: 150px 35px;
grid-gap: 0px;
display: grid;
cursor: pointer;
width: 100%;
font-size: 13px;
}
.project li:hover {
border-radius: 200px;
border: 1px solid;
padding-right: 160px;
}
.project li {
list-style-type: none;
grid-area: name;
padding: 10px;
margin: 10px;
}
.project .settings {
grid-area: settings;
text-align: center;
align-self: center;
font-size: 18px;
}
.project .settings:hover {
border-radius: 200px;
border: 1px solid;
padding-right: -160px;
}

Looks like this was due to the size I chose for the first grid column:
grid-template-columns: 150px 35px;
Which is fine except I was then adding padding and margins so it pushed the second grid out.
Resolved by changing it to:
grid-template-columns: auto 35px;
And setting my hover to
(note: In my example above I had the hover on the li tag)
.project:hover {
border-radius: 200px;
border: 1px solid;
border-width: 100%;
}

Related

CSS dynamically determine number of columns based on max-content of children

I'm trying to use css columns to display a dynamic number of columns based on the maximum width needed for the children to display nicely (such that the text doesn't wrap onto a new line where possible). I'd then like to stretch each element to fit the available space in the column.
This is what I have (Here is a JSFiddle):
But this is what I'd like to see (all elements have equal width):
This is the code I've tried:
<div class="columns">
<div>
Lorem
</div>
<div>
Ipsum
</div>
<div>
Dollar
</div>
<div>
Euro
</div>
<div>
Bitcoin
</div>
</div>
* {
padding: 0;
margin: 0;
}
.columns {
columns: auto;
column-gap: 1rem;
background: #4cafff;
padding: 1rem 0;
}
.columns > div {
width: max-content;
background: #4caf50;
color: white;
font-size: 2rem;
border: 2px solid green;
margin: 1rem;
}
max-content is not work like that. It is make the content not to wrap. I mean, width or height of content will be maximum size of your content. It will be fit.
If you want to equal width of all element, you can use specific pixel for width.
Like this:
.columns > div {
width: 95px;
text-align: center;
background: #4caf50;
color: white;
font-size: 2rem;
border: 2px solid green;
margin: 1rem;
}
Try this CSS
* {
padding: 0;
margin: 0;
}
.columns {
display: flex;
flex-wrap: wrap;
background: #4cafff;
padding: 1rem 0;
}
.columns > div {
background: #4caf50;
flex: 1;
color: white;
font-size: 2rem;
border: 2px solid green;
margin: 1rem;
}

Need all elements in a row to be the length of the longest sibling

I have some dynamically generated buttons, the button text may be a single word, or a small sentence. So I need the buttons to autosize to their content (i.e. can't use a fixed width).
But I also need all the buttons to be the same size, based on the size of the largest button. I know I can do this in JavaScript quite easily. I've provided an example of that below so you can see the expected result.
But I wondered if there was a way to do it just using CSS?
// Quick and dirty just for example purposes
document.addEventListener("DOMContentLoaded", function(event) {
var buttons = document.querySelectorAll('.container_two > button'),
biggest = {w:0, h:0};
buttons.forEach((btn) => {
var size = btn.getBoundingClientRect();
biggest.w = biggest.w < size.width ? size.width : biggest.w;
biggest.h = biggest.h < size.height ? size.height : biggest.h;
});
//console.log(biggest);
buttons.forEach((btn) => {
btn.style.width = Math.ceil(biggest.w)+'px';
// btn.style.height = biggest.h+'px'; -- flexbox will do this for us
});
});
strong { display: block; text-align:center;margin-bottom:1em; font-size: 20px; }
hr { margin: 1.5em 0 1em; }
button {
background: black;
color: white;
font-size: 16px;
padding: 0.5em 1em;
outline: none;
border-width: 0;
border-radius: 0.5em;
}
.container {
display: flex;
justify-content: center;
gap: 1em;
}
<strong>Original</strong>
<div class="container container_one">
<button>?</button>
<button>Yep sure, why not do it later?</button>
<button>Somewhere<br />over<br />the<br />rainbow</button>
</div>
<hr />
<strong>Javascript Solution</strong>
<div class="container container_two">
<button>?</button>
<button>Yep sure, why not do it later?</button>
<button>Somewhere<br />over<br />the<br />rainbow</button>
</div>
Try this:
Set the width of the container to shrink wrap the content (width: fit-content)
Use grid properties to distribute container space equally, which will set all buttons to the width of the longest element. (grid-template-columns: repeat(3, 1fr) or 1fr 1fr 1fr).
.container {
display: grid;
width: fit-content;
grid-template-columns: 1fr 1fr 1fr;
gap: 1em;
margin: 0 auto;
}
button {
background: black;
color: white;
font-size: 16px;
outline: none;
border-width: 0;
border-radius: 0.5em;
}
<div class="container">
<button>?</button>
<button>Yep sure, why not do it later?</button>
<button>Somewhere<br />over<br />the<br />rainbow</button>
</div>
Tested in Chrome, Firefox and Edge. Check fit-content in caniuse.com for full compatibility data.
I would recommend using flex-grow, just add it to the button and all buttons will grow to the same ratio if you make the ratio the same:
strong {
display: block;
text-align:center;
margin-bottom:1em;
font-size: 20px;
}
button {
background: black;
color: white;
font-size: 16px;
flex: 1; /* you can also use flex-grow: 1; */
padding: 0.5em 1em;
outline: none;
border-width: 0;
border-radius: 0.5em;
}
.container {
display: flex;
justify-content: center;
gap: 1em;
max-width: 813px;
margin: 0 auto;
/* change the width of the container in order to not fill the entire screen and keep to the required size */
}
<strong>Original</strong>
<div class="container container_one">
<button>?</button>
<button>Yep sure, why not do it later?</button>
<button>Somewhere<br />over<br />the<br />rainbow</button>
</div>

Position and centering of the circular shape inside the list cell in CSS

I have a problem with positioning and centering the round shape in the horizontal list cell.
I've a class for my cicrle:
.user-logo {
background-color: #4CAF50;
border: none;
border-radius: 50%;
height: 50px;
width: 50px;
text-align: center;
}
And class for the list:
.navbar-list {
#extend ul;
height: $navbar-height;
float: right;
li {
float:left;
}
a {
display: block;
margin: 0 auto;
padding-left: 5px;
padding-right: 5px;
}
li a:hover {
background-color: #111;
}
}
I'm working with react so class usage looks like this:
<ul className='navbar-list'>
<li><NavLink to='/'>New Project</NavLink></li>
<li><NavLink to='/'>Log Out</NavLink></li>
<li><NavLink to='/' className='user-logo'>NN</NavLink></li>
</ul>
How can I adjust the position of my circular shape inside a cell? For now, the text of my Navbar is well displayed - in the middle of every cell (even the text for my circle), but my circle is still aligned to the upper left corner of the cell.
You can use below CSS code:
.user-logo {
background-color: #4caf50;
border: none;
border-radius: 50%;
height: 50px;
width: 50px;
display: flex;
justify-content: center;
align-items: center;
}
.navbar-list {
height: 50px;
justify-content: flex-end;
display: flex;
align-items: center;
}
.navbar-list li {
list-style-type: none;
}
.navbar-list li a {
padding-left: 5px;
padding-right: 5px;
}
.navbar-list li a:hover {
background-color: #111;
}
One way is to make the parent element into a flexbox by doing:
li{ display: flex; }
For more info on flexbox css you can have a look here or other tutorials online.
Otherwise, make sure your circular shape has display: inline-block so that you can control its vertical positioning with margins and try to optimize with even top and bottom margins on the circular shape or top and bottom paddings on the parent element.

Create line after text with css

Im trying to make a line after each of my h2 tags. I canĀ“t figure out how I should tell the width, cause the lenght of the h2 headlines is differ from h2 to h2.
I use the :after method to create lines
h2:after {
position: absolute;
content: "";
height: 2px;
background-color: #242424;
width: 50%;
margin-left: 15px;
top: 50%;
}
Check code here: http://jsfiddle.net/s9gHf/
As you can see the line get too wide, and make the website too wide.
You could achieve this with an extra <span>:
h2 {
font-size: 1rem;
position: relative;
}
h2 span {
background-color: white;
padding-right: 10px;
}
h2:after {
content: "";
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 0.5em;
border-top: 1px solid black;
z-index: -1;
}
<h2><span>Featured products</span></h2>
<h2><span>Here is a very long h2, and as you can see the line get too wide</span></h2>
Another solution without the extra <span> but requires an overflow: hidden on the <h2>:
h2 {
font-size: 1rem;
overflow: hidden;
}
h2:after {
content: "";
display: inline-block;
height: 0.5em;
vertical-align: bottom;
width: 100%;
margin-right: -100%;
margin-left: 10px;
border-top: 1px solid black;
}
<h2><span>Featured products</span></h2>
<h2><span>Here is a very long h2, and as you can see the line get too wide</span></h2>
External examples: First, Second
There's no need for extra wrappers or span elements anymore. Flexbox and Grid can handle this easily.
h2 {
display: flex;
align-items: center;
}
h2::after {
content: '';
flex: 1;
margin-left: 1rem;
height: 1px;
background-color: #000;
}
<h2>Heading</h2>
using flexbox:
h2 {
display: flex;
align-items: center;
}
h2 span {
content: "";
flex: 1 1 auto;
border-top: 1px solid #000;
}
<h2>Title <span></span></h2>
Here is another, in my opinion even simpler solution using a flex wrapper:
.wrapper {
display: flex;
align-items: center;
}
.line {
border-top: 1px solid grey;
flex-grow: 1;
margin: 0 10px;
}
<div class="wrapper">
<p>Text</p>
<div class="line"></div>
</div>
External link
I notice that there are some flexbox implementations but they don't explain why and how to use it.
First, we just need one element, for this example h2.
We will change the element's display behavior to display: flex
Then, we center vertically its child elements using align-items: center.
h2 {
...
display: flex;
align-items: center;
}
Then, let's draw the line using the pseudo-element after.
We add '' to the content property to draw the element (we must).
Now lets make it flexible using flex: auto. This means that our element is sized according to its width and height properties. It grows to absorb any extra free space in the flex container, and shrinks to its minimum size to fit the container. This is equivalent to setting flex: 1 1 auto.
Then we add an small gap between the text and the line using margin-left: 1rem.
Finally, we draw a black line using border-top: 1px solid #000.
h2::after {
content: '';
flex: auto;
margin-left: 1rem;
border-top: 1px solid #000;
}
Here is functional snippet.
h2 {
font-size: 1em; /* not needed */
display: flex;
align-items: center;
}
h2::after {
content: '';
flex: auto;
margin-left: 1rem;
border-top: 1px solid #000;
}
<h2>Normal title</h2>
<h2>Very long title to test the behavior of the element when the content is wider</h2>
This is the most easy way I found to achieve the result: Just use hr tag before the text, and set the margin top for text. Very short and easy to understand! jsfiddle
h2 {
background-color: #ffffff;
margin-top: -22px;
width: 25%;
}
hr {
border: 1px solid #e9a216;
}
<br>
<hr>
<h2>ABOUT US</h2>
Here is how I do this:
http://jsfiddle.net/Zz7Wq/2/
I use a background instead of after and use my H1 or H2 to cover the background. Not quite your method above but does work well for me.
CSS
.title-box { background: #fff url('images/bar-orange.jpg') repeat-x left; text-align: left; margin-bottom: 20px;}
.title-box h1 { color: #000; background-color: #fff; display: inline; padding: 0 50px 0 50px; }
HTML
<div class="title-box"><h1>Title can go here</h1></div>
<div class="title-box"><h1>Title can go here this one is really really long</h1></div>
I am not experienced at all so feel free to correct things. However, I tried all these answers, but always had a problem in some screen.
So I tried the following that worked for me and looks as I want it in almost all screens with the exception of mobile.
<div class="wrapper">
<div id="Section-Title">
<div id="h2"> YOUR TITLE
<div id="line"><hr></div>
</div>
</div>
</div>
CSS:
.wrapper{
background:#fff;
max-width:100%;
margin:20px auto;
padding:50px 5%;}
#Section-Title{
margin: 2% auto;
width:98%;
overflow: hidden;}
#h2{
float:left;
width:100%;
position:relative;
z-index:1;
font-family:Arial, Helvetica, sans-serif;
font-size:1.5vw;}
#h2 #line {
display:inline-block;
float:right;
margin:auto;
margin-left:10px;
width:90%;
position:absolute;
top:-5%;}
#Section-Title:after{content:""; display:block; clear:both; }
.wrapper:after{content:""; display:block; clear:both; }

Vertically align inline object without height or width

Given the following html:
<div class="body">
<div class="banner">
<div class="name">
<h2>
<a href="http://www.example.com">
<span class="bold">Test Link</span><br/>
</a>
</h2>
</div>
<div class="title">
<h3>A Connections Learning Partner Program</h3>
<p>Quality online learning for high school students in Oakland County and surrounding counties.
</p>
</div>
<div class="link">
Learn More
</div>
</div>
</div>
How can I vertically align .link a (the button) within .link without giving a height or width? Like this...
Here's my fiddle
Here is one way that you can do it. Your HTML is good, no need to change anything.
For the CSS:
.body { width: 920px; }
.banner {
background-color: #454545;
border-bottom: 3px solid #F9F9F9;
height: 100px;
margin: 0 0 5px;
padding: 0;
display: table;
}
.banner > div {
outline: 1px dotted yellow; /* optional to show cell edges... */
display: table-cell;
}
.banner .name {
width: 25%;
vertical-align: top;
padding-top: 25px; /* control top white space */
text-align: center;
}
.banner .name h2 {
color: #F9F9F9;
max-height: 55px;
text-transform: uppercase;
margin: 0;
padding: 0;
}
.banner .title {
width: 50%;
vertical-align: top;
padding-top: 25px;
}
.banner .title h3 {
font-size: 15px;
font-weight: bold;
line-height: 15px;
margin: 0px 0 0 0;
padding: 0;
}
.banner .title p {
font-size: 12px;
max-height: 35px;
overflow: hidden;
margin: 0;
padding: 0;
}
.banner .link {
width: 25%;
vertical-align: middle;
text-align: left; /* set to left, center or right as needed */
}
.banner .link a {
margin-left: 25px; /* controls left offset */
background-color: #FA9800;
border-radius: 5px 5px 5px 5px;
cursor: pointer;
display: inline-block; /* use inline-block if you want to center element */
font-size: 12px;
font-weight: bold;
height: 23px;
line-height: 23px;
text-align: center;
text-decoration: none;
width: 100px;
}
See the fiddle at: http://jsfiddle.net/audetwebdesign/jsG8F/
How This Works
The trick is to use display: table on your .banner container and then display: table-cell on your child div elements, and set the % widths to 25%, 50%, 25% respectively for .name, .title, .link.
You can then use vertical-align and text-align to control vertical and horizontal placement of the various text blocks.
I added comments related to using padding-top to control white space from the top of the banner.
For the .link a element, you can adjust the left margin (or right) as needed.
These CSS rules offer you a lot of fine control over the placement of the various elements within the banner.
Backwards Compatibility
The display: table-cell property is backwards compatible back to IE8.
Reference: https://developer.mozilla.org/en-US/docs/Web/CSS/display
If the size of the element and banner are fixed, use margin-top to offset the element.
Marc Audet was very close but I ended up going a slightly different route.
I gave .link a a fixed top margin and made margin-left: auto; and margin-right: auto; and that did the trick.
Here is the fiddle for reference.

Resources