I have a bunch of buttons and I want them to all be the same width without having to set a specific width, so naturally you would want the width of all buttons to take the width of the widest element, but I am having a hard time achieving this with flex as it seems it just wants them all to be 100%; I also tried it with a wrapper around the anchors but that didn't help as then the buttons were all varying widths.
CodePen: https://codepen.io/gutterboy/pen/MZWroj?editors=1100
So in that example, all the buttons should match the natural width of what the "Groundskeeping" would be.
HTML:
<div class="container">
<div class="row">
<div class="offset-md-4 col-md-4">
<div class="buttons">
Plumbing
Electrical
Groundskeeping
Construction
Cleaning
Security
Trades Assistant
General Duties
</div>
</div>
</div>
</div>
CSS:
.buttons {
display: flex;
flex-direction: column;
padding: 15px;
background-color: gray;
.btn {
display: block;
margin-bottom: 11px;
&:last-child {
padding-bottom: 21px;
}
}
}
a.btn {
display: inline-block;
text-align: center;
height: 35px;
padding: 0 20px;
min-width: 128px;
font-weight: bold;
color: #fff;
background-color: orange;
border: 2px solid #000;
white-space: nowrap;
text-decoration: none;
}
Is there any way this can be done in Flex or anything else?
You are almost good, you should use inline-flex instead of flex to have the shrink-to-fit behavior thus the biggest button will define the width of the container and all the elements are by default stretched to that width:
.container {
margin-top: 15px;
text-align:center;
}
.buttons {
display: inline-flex;
flex-direction: column;
padding: 15px;
background-color: gray;
}
.buttons .btn {
display: block;
margin-bottom: 11px;
}
.buttons .btn:last-child {
padding-bottom: 21px;
}
a.btn {
display: inline-block;
text-align: center;
height: 35px;
padding: 0 20px;
min-width: 128px;
font-weight: bold;
color: #fff;
background-color: orange;
border: 2px solid #000;
white-space: nowrap;
text-decoration: none;
}
<div class="container">
<div class="buttons">
Plumbing
Electrical
Groundskeeping
Construction
Cleaning
Security
Trades Assistant
General Duties
</div>
</div>
Related
I have a button inside a grid cell whose size is determined by font-size as em and padding as percentage.
I require the text of the button to not wrap.
Initially, I used <button type="button" id="log_out_button" data-action="manual_log_out">log out</button> but this produced an undesired result - it wrapped the text:
log
out
I added white-space: nowrap to the button to fix this but it made the button exceed its parent by 0.5cm, which decentralises my grid by the same amount.
To try fixing this knock-on problem, I changed the button to <input type="button" value="log out" id="log_out_button" data-action="manual_log_out">, to no avail.
I added box-sizing: border-box to the button, to no avail.
I experimented with grid-template-columns: auto auto auto; (third value), trying the various options listed Chrome's dev console, to no avail.
Prior to the navigation being a grid, it was a flexbox that had the same problem.
I want my site scalable so I can't set fixed values i.e. in pixels, and setting the percentage of the cell (grid-template-columns) still results in an offset/decentralisation.
How do I prevent my 'log out' button's text from wrapping and prevent it from exceeding its parent's width, such that I avoid the grid's decentralisation issue?
Problem code:
<html>
<head>
<style type="text/css">
body {
font-family: Arial;
background-color: white;
font-size: 1.5vh;
}
header {
height: 100%;
margin: auto;
height: 10.9%;
width: 100%;
}
nav {
margin: auto;
align-items: center;
justify-content: center;
height: 100%;
display: grid;
grid-template-columns: auto auto auto;
grid-gap: 2.5%;
}
nav a, nav a:visited {
text-decoration: none;
color: black;
}
#user_identity {
display: flex;
justify-content: center;
flex-flow: column;
align-items: flex-end;
}
#navigation_menu_wrapper {
height: 100%;
}
#navigation_menu {
flex: 1;
display: flex;
height: 100%;
align-items: center;
}
#navigation_menu div {
text-align: center;
padding-left: 15px;
padding-right: 15px;
font-size: 1.125em;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: rgb(205, 255, 205);
border-right: 1px solid rgb(157, 189, 157);
}
#navigation_menu a {
display: block;
padding: 7px 12px 7px 12px;
border-radius: 3px;
cursor: pointer;
}
#log_out_wrapper {
display: flex;
justify-content: flex-start;
align-items: center;
height: 100%;
}
#username_label {
font-family: "Optima Bold";
font-size: 1.87em;
color: rgb(72, 160, 72);
}
#permanent_id_label {
font-size: 1em;
color: rgb(146, 146, 146);
font-weight: bold;
margin-left: 9px;
cursor: default;
}
#mobile_menu_control {
display: none;
}
#log_out_button {
padding-top: 7%;
padding-bottom: 8%;
border: none;
border-radius: 3px;
background-color: #8dc49d;
text-align: center;
padding-left: 12%;
padding-right: 12%;
font-size: 1.25em;
cursor: pointer;
}
</style>
</head>
<body>
<div id="wrapper">
<header>
<nav>
<div id="user_identity">
<div id="username_label">texthere</div>
<div id="permanent_id_label">#texthere</div>
</div>
<div id="navigation_menu_wrapper">
<button id="mobile_menu_control">menu</button>
<div id="navigation_menu">
<div>
link1
</div>
<div>
link2
</div>
<div>
link3
</div>
<div>
link4
</div>
<div>
link5
</div>
<div>
link6
</div>
</div>
</div>
<div id="log_out_wrapper">
<input type="button" value="log out" id="log_out_button" data-action="manual_log_out">
</div>
</nav>
</header>
<div id="content_wrapper"></div>
</div>
</body>
</html>
As suggested by commenters, applied the following jQuery/JavaScript fix:
logOutButtonWidth = 0;
$(document).ready(function() {
centraliseHeader();
$(window).resize(function() {
centraliseHeader();
});
});
function centraliseHeader() {
logOutButtonWidth = $("#log_out_button").outerWidth();
$("nav").css({
gridTemplateColumns: "auto auto " + logOutButtonWidth + "px"
});
}
If I comment out my Div wrapper, the page becomes a jumbled mess, if the wrapper is not commented out, it is not a jumbled mess.
Why? My guess is that is is somehow shielded from the CSS, but I am not sure.
I am new so, I apologize in advance.
This exercise is part of the OdinProject, and is the first one I'm actually struggling with understanding.
html,
body {
height: 100%;
}
.header {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 18px;
font-weight: 700;
margin-bottom: 8px;
}
body {
font-family: Roboto, sans-serif;
margin: 0;
background: #aaa;
color: #333;
/* I'll give you this one for free lol */
display: flex;
align-items: center;
justify-content: center;
}
.modal {
display: flex;
gap: 16px;
padding: 16px;
background: white;
width: 480px;
border-radius: 10px;
box-shadow: 2px 4px 16px rgba(0, 0, 0, .2);
}
.icon {
flex-shrink: 0;
color: royalblue;
font-size: 26px;
font-weight: 700;
background: lavender;
width: 42px;
height: 42px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.close-button {
background: #eee;
border-radius: 50%;
color: #888;
font-weight: 400;
font-size: 16px;
height: 24px;
width: 24px;
display: flex;
align-items: center;
justify-content: center;
}
button {
padding: 8px 16px;
border-radius: 8px;
}
button.continue {
background: royalblue;
border: 1px solid royalblue;
color: white;
}
button.cancel {
background: white;
border: 1px solid #ddd;
color: royalblue;
}
.text {
margin-bottom: 16px;
}
<div class="modal">
<div class="icon">!</div>
<div class="wrapper">
<div class="header">Are you sure you want to do that?
<div class="close-button">✖</div>
</div>
<div class="text">text</div>
<button class="continue">Continue</button>
<button class="cancel">Cancel</button>
</div>
Your .modal has the display: flex property. This property applies to all direct children of the .modal element.
If you remove the .wrapper, the elements in the modal are no longer grouped together and they are treated as separate flex items. This is why they appear side to side (.icon, then .header, then .text, then .button all on the same line).
Here is a great guide on the display: flex property.
All HTML elements have default properties. A div has one: display: block;. In this case, when your wrapper div is removed, this property is removed it breaks the appearance because this default is battling the parent element's display: flex property.
Here's the default property list: https://www.w3schools.com/cssref/css_default_values.asp
I'm trying to make the link have a focus state around the whole .container-covid-alert div, when the link is tabbed onto, I'm sure this must be possible? The below 2 selectors are not working.
.container-covid-alert:focus {
outline: solid 3px #FFAD16;
}
.container-covid-alert a:focus {
outline: solid 3px #FFAD16;
}
.container-covid-alert {
background-color: #206497 !important;
color: #FFFFFF;
padding-top: 10px;
padding-bottom: 10px;
display: block;
flex-flow: row wrap;
align-items: center;
align-content: center;
justify-content: flex-start;
font-size: 1.1rem;
}
.container-covid-alert a {
color: #FFFFFF;
}
.covid-inner {
margin: auto;
width: 1170px;
}
<a id="covid-banner-link" title="Coronavirus" class="sys_16" href="/">
<div class="container-covid-alert">
<div class="covid-inner">
<p>Coronavirus (COVID-19)updates and advice.</p>
</div>
</div>
</a>
Your hyperlink collapses as it behaves as an inline element.
The solution is to make it act like a block element with display: block;.
That way you can just add the :focus state to the hyperlink itself and make it really simple.
Also an orange focus indicator is not high enough contrast - it is only 1.86:1 and you need 3:1 as a minimum so you may want to change that.
#covid-banner-link{
display:block;
}
#covid-banner-link:focus {
outline: solid 3px #FFAD16;
}
.container-covid-alert {
background-color: #206497 !important;
color: #FFFFFF;
padding-top: 10px;
padding-bottom: 10px;
display: block;
flex-flow: row wrap;
align-items: center;
align-content: center;
justify-content: flex-start;
font-size: 1.1rem;
}
.container-covid-alert a {
color: #FFFFFF;
}
.covid-inner {
margin: auto;
width: 1170px;
}
<a id="covid-banner-link" title="Coronavirus" class="sys_16" href="/">
<div class="container-covid-alert">
<div class="covid-inner">
<p>Coronavirus (COVID-19)updates and advice.</p>
</div>
</div>
</a>
As you can see in the snippet below, I have 1 div which has display property set to flex and then this div has 2 children divs which take flex:1 space ( 50% ). Each of those divs contains 1 button each.
Now the problem is this. I want the first button to be at the start of the first div ( so left side ) and the second button to be at the end of the second div ( so right side ). Currently both buttons are at the left side of their respective divs.
And while we're at it, is using flexbox the best way to create side by side divs like I've done nowadays?
.edit-btn, .submit-btn {
display: block;
color: black;
cursor: pointer;
text-align: center;
border-radius: 4px;
border: none;
padding: 8px 10px 8px 10px;
line-height: 1.2;
outline:none;
}
.flex-row {
display: flex;
margin-bottom: 10px;
}
.flex-column {
flex: 1;
}
.like, .edit {
width: 150px;
font-size: 13px;
}
.submit-btn {
background-color: #4CAF50;
}
.edit-btn {
background-color: #13aff0;
}
<div class="flex-row">
<div class="flex-column">
<button class="submit-btn like">Like</button>
</div>
<div class="flex-column">
<a class='edit-btn edit' href="#">Edit</a>
</div>
</div>
You don't need .flex-column wrappers. And use justify-content: space-between;
.edit-btn,
.submit-btn {
display: block;
color: black;
cursor: pointer;
text-align: center;
border-radius: 4px;
border: none;
padding: 8px 10px 8px 10px;
line-height: 1.2;
outline: none;
}
.flex-row {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
}
.like,
.edit {
width: 150px;
font-size: 13px;
}
.submit-btn {
background-color: #4CAF50;
}
.edit-btn {
background-color: #13aff0;
}
<div class="flex-row">
<button class="submit-btn like">Like</button>
<a class='edit-btn edit' href="#">Edit</a>
</div>
So it looks like this:
this is the example code of a message:
.allMsg {
width: 100%;
}
.self {
border-radius: 1rem;
background-color: #28a745;
text-align: right;
padding-left: 5px;
padding-right: 5px;
margin-left: 5px;
margin-right: 5px;
}
.friend {
text-align: left;
}
#chatWith {
text-align: center;
font-family: sans-serif;
font-size: 40px;
padding-bottom: 15px;
border-bottom: 1px solid #eee;
}
<div class='allMsg'>
<p class='self chatMsg'>Hello</p>
</div>
How can i make the border as big as the text inside ... I thought the padding was going to work but unfortunately it didn't so please help me.
It's possible if you wrap your messages inside another element. So let's say all messages have a full-width element, but friends messages will aligned to the left and have a blue background, while yours will aligned to the right and have a green background. If you don't want to change your markup so much, the easiest is to wrap your messages inside a span, than you doesn't need to change anything else in your html.
.allMsg {
width: 100%;
}
.self span, .friend span {
border-radius: 1rem;
padding-left: 5px;
padding-right: 5px;
margin-left: 5px;
margin-right: 5px;
}
.self span {
background-color: #28a745;
}
.friend span {
background-color: #2845a7;
}
.self {
text-align: right;
}
.friend {
text-align: left;
}
<div class='allMsg'>
<p class='chatMsg friend'>
<span>hello</span>
</p>
<p class='chatMsg self'>
<span>hy</span>
</p>
<p class='chatMsg friend'>
<span>how are you friend?</span>
</p>
<p class='chatMsg self'>
<span>i'm fine thanks</span>
</p>
</div>
You could use flexbox on the container:
.allMsg {
width: 100%;
display: flex;
flex-flow: column nowrap;
align-items: flex-end;
}
Example:
.allMsg {
width: 100%;
display: flex;
flex-flow: column nowrap;
align-items: flex-end;
}
.self {
border-radius: 1rem;
background-color: #28a745;
text-align: right;
padding-left: 5px;
padding-right: 5px;
margin-left: 5px;
margin-right: 5px;
}
.friend {
text-align: left;
}
#chatWith {
text-align: center;
font-family: sans-serif;
font-size: 40px;
padding-bottom: 15px;
border-bottom: 1px solid #eee;
}
<div class='allMsg'>
<p class='self chatMsg'>Hello</p>
<p class='self chatMsg'>This is a test</p>
</div>