centering a div which have left aligned contents - html

I am trying to build a website which I also use angular. I need to perfectly centre a div element which contains some icons (around 80) and those icons must be left aligned. Contents are filtered via text input and this filtration results in different numbers of icons every time. I've tried a grid system similar to a bootstrap's grid, flexbox, whatever. Either a small extra area is left blank on the right side when I align my contents to left, or all the elements are centred and the bottom elements are centred and the div does not look organized. Moreover, I need to keep at least 10 px of margins between each icon. Can anyone help me?
.notfound {
text-align: center;
}
.iconelement:hover {
background-color: #ffffff;
box-shadow: 0 1px 6px 0 rgba(0, 0, 0, 0.16);
color: #000000;
}
.iconelement:active {
background-color: #2974d4;
box-shadow: 0 1px 6px 0 rgba(0, 0, 0, 0.16);
color: #ffffff;
}
.grid-container {
background-color: #fdfdfd;
padding-bottom: 20px;
display: flex;
justify-content: center;
text-align: left;
flex-wrap: wrap;
}
.iconelement {
width: 60px;
height: 60px;
border-radius: 4px;
background-color: #fdfdfd;
text-align: center;
margin: 10px;
float: none;
color: #000000;
}
.icons {
position: relative;
top: 50%;
transform: translateY(-50%);
font-size: 2em;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="ui-g ">
<div class="ui-g-12" *ngIf="(icons|filter:searchText).length===0">
<div class=" ui-g-12 notfound">
<h3>No results for "{{searchText}}"</h3>
</div>
</div>
</div>
<div class="ui-xl-3 ui-lg-3 ui-md-2 ui-sm-1" (click)="unselectIcon()"></div>
<div class=" ui-xl-6 ui-lg-6 ui-md-8 ui-sm-10 ">
<div class="ui-g-12 grid-container">
<div class="ui-g-1 iconelement" *ngFor="let icon of icons| filter : searchText; let i = index " (click)="getIcon(icon.id)">
<i class="icons {{icon.name}}"></i>
</div>
</div>
</div>
<div class="ui-xl-3 ui-lg-3 ui-md-2 ui-sm-1" (click)="unselectIcon()"></div>
</div>
ps: text align: center does not solve this problem.

If your goal is to create a responsive auto-centering container where items (icons) maintain the same width while the gaps between items adapt, your best way to do that currently is probably flexbox (and grids in the future). An example here.
The issue with flexbox based layouts, though, is how to have the last row aligned to the left. You could try some of the solutions proposed in this thread, however they work only in certain situations. Oftentimes you would need to use javascript to achieve this. I created a function for that and could post it somewhere should you be interested.
Generally, when you're dealing with this kind of a problem, you should consider, which elements need to adapt. Whether the gap between elements, the elements themselves or the container where elements reside.
Flexible gap - fixed elements - fixed/flexible container
Manageable by the approach I described above - flexbox to stretch the gap, fixed width on the elements and possibly javascript to align last row.
Fixed gap - flexible elements - fixed/flexible container
Fixed padding and flex attribute on the element.
Fixed gap - fixed elements - fixed container
Use float: left on the elements and put all into a container of defined dimensions. The container's width must be in multiples of elements width + padding to be centered, affected by how many elements should be on each line.
Fixed gap - fixed elements - flexible container
This is fairly well doable with flex attribute again. Often though there is a need to set a minimal width and we're back at case #1.
So achieving a fully responsive centered element with left-aligned items is currently a challenge. If you need perfection at all costs, I'd suggest using several media queries instead to make sure it always looks the way you want (As discussed here for example).

I have found my solution but it was not in the way I've wanted. I've got rid of all the ui-g grid layout except the grid itself. (the main reason that I've been using it is to run my page on all browsers, ie11 cause many problems with new technologies) I also used flex (flex-wrap as recommended) to keep the elements in the div.
That way the icons covered 100% of the screen in width.
To contain the items I have a maximum width but this meant that the responsiveness of the container is not there anymore. that is why I don't like this solution. To patch this, I used #media screen to adjust the number of elements displayed depending on the screen size.
To make it perfect it needed many trials and errors but a fix is a fix.
Fixing all the elements is done by "margin: auto;"
here is the code after fix:
<div class="ui-g">
<div class="notfound" *ngIf="(icons|filter:searchText).length===0">
<h3>No results for "{{searchText}}"</h3>
</div>
<div class="ui-g-12 grid-container">
<div class="ui-g-1 iconelement" *ngFor="let icon of icons| filter : searchText; let i = index "(click)="getIcon(icon.id)">
<i class="icons pi pi-{{icon.name}}" ></i>
</div>
</div>
In the div at the top I still use class=ui-g" to push down the sticky element which displays the icon details.
Each icon has the width and height of 60 px and has 10 px margin, so I needed to calculate the sum of the width and apply it according to the screen and how many icons I need to see side by side.
CSS:
.notfound {
text-align: center;
margin: auto;
width: 100%;
}
.iconelement:hover {
background-color: #ffffff;
box-shadow: 0 1px 6px 0 rgba(0, 0, 0, 0.16);
color: #000000;
}
.iconelement:active {
background-color: #2974d4;
box-shadow: 0 1px 6px 0 rgba(0, 0, 0, 0.16);
color: #ffffff;
}
.grid-container {
background-color: #fdfdfd;
padding-bottom: 20px;
display:flex;
flex-wrap: wrap;
max-width: 660px;
margin: auto;
}
.iconelement {
width: 60px;
height: 60px;
border-radius: 4px;
background-color: #fdfdfd;
text-align: center;
margin: 10px;
float: none;
color: #000000;
}
.icons {
position: relative;
top: 50%;
transform: translateY(-50%);
font-size: 2em;
}
#media screen and (max-width: 430px) {
.grid-container{
max-width: 260px;
}
}
the last bit is for the width configuration.

Related

Placing two select elements vertically one above the other, with centrally aligned horizontally

I want two dropdown menus, one below other, and then I need more stuff aligned below that as well (say a button below these two).
I thought to combine all of these in a div.
My DIV is classed as .filter-search
and both drop downs are classed as .drop
CSS code below.
.filter-search {
margin-left: 10%;
margin-right: 10%;
margin-top: 40px
}
.drop {
display: block;
margin: auto;
font-size: 18px;
padding: 12px 360px 12px 8px;
border: 2px solid black;
border-radius: 8px;
background-color: white;
}
My problem currently is that even though both drop downs (1 and 2) have the same text, even then the size of the dropdowns differs by a small fraction. i.e. they aren't aligned left and right.
I can make them same by setting the width as 50%, but I am trying to understand why it isn't working by itself (if all the CSS attributes of both select dropdowns are the same).
Also, I am wondering if I really need the outer div in this case?
Without debugging your page it is difficult to say exactly what the problem is.
I have created a JSFiddle with an example, where i think it works like you wanted: https://jsfiddle.net/zag8hsL3/1/
The important part is the
display: flex;
flex-direction: column;
align-items: center;
justify-content: center
on the .selects wrapper div.
Let me know if this isn't exactly what you wanted, and we can change it... 😉

Css flexbox content overflows

I have the following header with items and am using flexbox
<header class="header">
<div class="row container header__items">
<h2 class="header__logo">Test</h2>
<input type="text" class="input input--outlined" placeholder="Serach">
<h5>Karim</h5>
<h5>Karim</h5>
<h5>Karim</h5>
</div>
</header>
And my scss code with flexbox classes i have
.header{
height: 50px;
background-color: white;
box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);
display: flex;
align-items: center;
&__items{
display: inherit;
flex-direction: row;
align-items: center;
background-color: red;
}
&__logo{
font-size: 35px;
font-weight: 200;
color: inherit;
}
}
The following has the header__items overflowing on the y-axis. How can i stop this. See the attached screenshot on the red background. Also it doesn't center the red box even if i reduce its height.Am using materialize css. I have also created https://codepen.io/geowan/pen/gOpzOEm which shows this.
Yash - there are so many things wrong with your markup. Firstly, Materializecss have already created a navbar for you - why re-invent the wheel? They don't use flexbox, but you can adapt their example to create what you need.
https://materializecss.com/navbar.html
Secondly, you are using a row inside a div that is also a container - and there are no cols inside. Here's how it works:
.container
This restricts the width of content. Consider it the inner-wrapper.
.row
Rows sit inside containers - they add margin-bottom for spacing, and are a container for cols.
.col
cols sit inside rows and lay your content out in columns. Please refer to the grid system, you are not suing elements as per the documentation.
https://materializecss.com/grid.html
input {
width: auto !important;
}
.links {
display: flex;
}
In terms of fixing your code, I removed .row from the element, put justify-content:space-between on the header__items to force the three items away from each other, wrapped your right hand links in a new div (and display: flex on these) and then changed the input width to auto, because the materialize default is 100% (so it was spreading the available width of your div.
https://codepen.io/doughballs/pen/MWwGwme
You need to spend some time in the docs and use the provided examples until you know what you're doing.

Have elements next to each other

I've been looking around, and haven't found a way to get my elements to display the way I want them too (Mostly because I've absolutey no idea what I'm doing in CSS).
Here's my JS fiddle:
https://jsfiddle.net/q0qjhk8p/2/
And here's an ASCII demonstation on how I wish for it to be displayed:
Title goes here
----------------------------------------------------------------------------
Content put here should be on [ image
the left side, yet not affect the goes
avatar on the right. here ]
And this
text should
be centered
underneath the
image.
---------------------------------------------------------------------------
Blablablablaba footer
So here's a solution using FlexBox
The things to note are...
I removed all your text-align stuff. That's the wrong property to use to get the layout you're looking for.
I made the Avatar container a percentage width, and set the width of the image inside to 100%. That way you have a somewhat responsive solution. You could set an explicit width of the avatar container if you wanted.
You can set an explicit width for the copy too, if you wanted. I'd suggest setting a percentage width and a right margin.
The heavy lifting is done with flexbox,
.user-profile-card > .user-profile-card-body {
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 10px;
background: #AAA;
}
I've added some extra divs and also used the following CSS
float : left // float to content to the left side
float : right // float the avatar to the right side of the card.
display : inline-box // this is to make the image stay on the same line as the content
see fiddle below
https://jsfiddle.net/n4k469o3/
CSS
.user-profile-card {
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
transition: 0.3s;
border-radius: 5px;
padding: 10px;
border: solid 1px transparent;
}
.content {
width:100px;
display: inline-block;
float: left;
}
.user-profile-card:hover {
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2)
}
.user-profile-card > .user-profile-card-title {
padding-bottom: 10px;
border-bottom: solid 1px #ccc;
text-align: left;
font-size: 24px;
}
.user-profile-card > .user-profile-card-body {
padding: 10px;
text-align: left;
}
.user-profile-card > .user-profile-card-body > .user-profile-card-avatar {
align-content: right;
text-align: right;
display: inline-block;
width: 110px;
float: right;
}
.img-card-avatar {
border-radius: 50px;
}
.user-profile-card > .user-profile-card-foot {
padding-bottom: 5px;
padding-top: 10px;
border-top: solid 1px #ccc;
text-align: left;
font-size: 10px;
margin-top:240px;
}
HTML
<div class="user-profile-card">
<div class="user-profile-card-title">
A title is put here
</div>
<div class="user-profile-card-body">
<div class="content">
Content put here should be on the left side, yet not affect the avatar on the right.
</div>
<div class="user-profile-card-avatar">
<img src="https://i.stack.imgur.com/pH9qA.jpg"><br>
And this text should be centered underneath the image.
</div>
</div>
<div class="user-profile-card-foot">
Some footer stuff is put here.
</div>
</div>
The simplest way to do this is to wrap the main content in a div. Then wrap that and the div with the image and subtext in another div. I have wrapped them in main tag below, just so that stands out, but you can use a div if you're not familiar with semantic tags just yet.
https://jsfiddle.net/g90xxaaj/
Then I gave the main tag a css property of display: flex this makes the divs inside it sit side by side.
Then I added have the div encasing the image and subtext a `text-align: center' property.
You don't have to use flexbox for this but it is an excellent way to deal with things like this is css. The other way you could do it is to look into something called floats. Joshua Duxbury's answer explains how to do this. One reason not to use flexbox is that it is relatively new and won't work on internet explorer 9 or older. If that is not a concern then flexbox is much less confusing than working with floats in the long run.
This is probably the best starting point for learning more about flexbox : https://css-tricks.com/snippets/css/a-guide-to-flexbox/
This is a great game to play for practice: http://flexboxfroggy.com/
And here is a fantastic free course if you have the time and are serious: https://flexbox.io/

clearing after a float left creates a void between two divs

I have the following part of my html
<div class="header">
<div class="header-bar">
<div class="pull-left">
<div class="title">Ci models database</div>
</div>
</div>
<div class="clear-both"></div>
<ol class=breadcrumb>
<li class="active">All models</li>
</ol>
</div>
the css(breadcrumb and active classes are bootstrap)
.header-bar {
border: None;
background-color: #66CCFF;
min-height:30px;
}
.title {
padding: 5px 5px 10px 5px;
color: white;
font-size: large;
}
.clear-both{
clear:both;
}
But between header-bar and breadcrumb html added a white space(see bootply). How can I remove this white space, since no padding and margin can be found between to divs.
The problem is that the calculated height of the internal .title div is greater than the calculated height of the container .header-bar. Properties like height, min-height, border, padding can directly effect heights, whereas properties like display, box-sizing and position can all indirectly effect height.
The result is the internal .title div pushes down the next div in the flow by 10px.
CSS has no rules that say a div must contain it's children in height and stop them from effecting other divs, even when height is directly defined. We need to tell it exactly how it should behave when things are rendered.
There are several ways to fix this:
http://www.bootply.com/Qa1ME2M2uk - use overflow: hidden; on the parent. Overflow is a css property which is used how to control what happens when child elements are larger than their parents. It's worth noting that depending on other properties overflow won't necessarily render itself in a way that disrupts layout.
http://www.bootply.com/ssq3EAzeyk - set explicit heights to take strict control over the dimensions of the elements. This might be the best option for a header bar.
http://www.bootply.com/yeodYRLLJk - set a greater min-height on the parent, one which will definitely contain the child. This is useful if your padding is for alignment purposes - setting min-height: 40px; in the example does this.
http://www.bootply.com/GznfJxUWUF - remove the padding that is making the element calculate as taller (as mentioned in another answer).
Apostolos, the white space is coming from the .titleclass.
The bottom padding of 10px.
Zero this and the white space will go.
.title {
padding: 5px 5px 0px 5px;
you will have to add a float: left to both parent containers (.header-bar and breadcrumb) otherwise the clear won't affect anything. furthermore you will have to give both containers width: 100%
.header-bar {
border: None;
background-color: #66CCFF;
min-height:30px;
width: 100%;
float: left;
}
.breadcrumb {
width: 100%;
float: left;
}
.title {
padding: 5px 5px 10px 5px;
color: white;
font-size: large;
}
.clear-both{
clear:both;
}

Position divs as follow without float

I have a web page which looks like this :
I would like to know if it is possible to have different margin-top value for the 2 outer divs. At the moment, whether I set margin : x% or margin : [value]px both outer div will receive the value from the margin. I would like it to affect only the one I set.
I mention without float because I was having problem with float and margin / width properties, but if you can come up with a proper solution using float, that'll float my boat. :)
Thanks a lot.
I'm a CSS newbie by the way so be easy on me
do you mean something like this ?
JSFIDDLE
html
<div class="container">
<div class="aaa">first</div>
<div class="bbb">second</div>
<div class="ccc">third</div>
</div>
<div class="container">
<div class="aaa">first</div>
<div class="bbb">second</div>
<div class="ccc">third</div>
</div>
css
div:not(.container){
margin: 10px 20px 30px 20px;
background: white;
height: 100px;
}
.container{
float: left;
background: black;
padding: 20px;
width: 200px;
margin-top: 25px; /*sets both divs same top*/
}
.container:not(:first-child){
margin-left: 50px;
/*margin-top: 25px*/ /*sets only second div or all others down and leaves
the first div like it is. but this for you have to
delete the margin-top entry from .container{ */
}
but actually i would use diffrent classes for this so you can set every div with his own css configuration :)
like:
.myFirstDivContainer{
/* pos data here */
}
.mySecondDivContainer{
/* pos data here */
}
and so on
EDIT
see :not() compabilitys
you can also use :nth-child() like
div.container:nth-child(0){
/* data for your first div */
}
div.container:nth-child(1){
/* data for your second div */
}
and so on...
you can use multiple css classes in the class attribute on an html element:
<div class="outer-div-wrapper">some content</div>
<div class="outer-div-wrapper larger-margin">some content</div>
then put in place some css rules:
/* this will give all divs with class 'outer-div-wrapper' a margin-top of 10px */
.outer-div-wrapper {
margin-top: 10px;
display: inline-block;
margin-right: 10px;
}
/* This will increase the margin size for the divs with the extra 'larger-margin' class */
.outer-div-wrapper.larger-margin {
margin-top: 15px;
}
Something just as good as margin-top in your case might be:
.second-div {
position: relative;
top: 15px;
}
This will move the second div 15px down relative to its default position.
BTW, you should get used to JSFiddle, it's a very good prototyping tool, and far better than making non-interactive drawings :)
Here's your drawing as a fiddle!