flexbox ios space distribution issues - html

Take a look at this image:
As you can see the 2 end links break out of the anchor container.
This is only happening on an iPad (using simulator to test).
On the desktop it behaves as it should by breaking the words in the other links allowing for more space to distribute the remaining items.
It's as if ios doesn't know how to properly break the text in the first link.
.nav-section {
padding: 0 30px;
}
.nav-section__list {
display: inline-flex;
align-items: stretch;
margin: 0 auto;
}
.nav-section__item {
padding: 0 20px;
}
.nav-section__link {
display: block;
background: red;
}
<nav class="nav-section">
<div class="nav-section__list">
<div class="nav-section__item">
AAAAA AAAA-AAAAAAAA AAAAAAAAA
</div>
<div class="nav-section__item">
AAA AAAAAAAA AAAAAAAAAA
</div>
<div class="nav-section__item">
AAAAAAAAAAA
</div>
<div class="nav-section__item">
AAAAAAA
</div>
</div>
</nav>
Update
word-break: break-all is not a valid solution:
word-wrap: break-all also doesn't work:
This is the same resolution but on a desktop:
As you can see the way the words break is completely different. The iPad just doesn't want to co-operate.
Update 2
I have run into the same issue in another instance of flexbox. It seems like IOS still has some bugs with the implementation.
So I went ahead and used display: table; and display: table-cell; just until the issue is resolved.
If anybody has any other hints as to exactly why the issue might be happening that would be great. Thanks!

Flexbox is relatively new, and browsers may have implemented it a little diferently from each other.
You may be missing the -webkit-prefix, as it looks like safari did need it on some versions.
display: -webkit-inline-flex;
display: inline-flex;
-webkit-align-items: stretch;
align-items: stretch;
Or, maybe you could try using:
word-break: break-all;
To ensure that those words will be broken, and will not overflow.

Must specify Width in nav-section__item
.nav-section__item {
padding: 0 20px;
word-wrap: break-all;
width: 20%;
}
Live Demo

In my experience with safari and flexbox it often helps to just add
display: flex;
flex-shrink: 0;
to the container which is too small. That should guarantee that the container is atleast the size of its contained element.

Related

Why is my Flexbox layout not working properly in Safari 15 and in Chrome?

I'm new to front end development and currently working on a website project.
It has a simple layout and I'm using CSS Flexbox to execute it. Works well in for example Firefox, and very poorly in Safari. I've done quite a bit of research and found out that Flexbox is not fully supported in older versions of Safari, however I have the newest version. Sizing and positioning doesn't work properly, aligning the items horizontally works.
Below is the desired look of one of the pages, in Firefox:
image
Below is the same page in Safari (it looks the same in Chrome):
image
When zooming out in Safari it looks like this:
image
.container4 {
font-family: "Chakra Petch", sans-serif;
font-size: 40px;
display: flex;
justify-content: center;
align-items: stretch;
gap: 50px;
.element4 {
padding-left: 50px;
padding-top: 50px;
align-self: flex-start;
flex: 1 1 50px;
}
.element4-2 {
padding-right: 50px;
padding-top: 50px;
align-self: flex-start;
flex: 1 1 50px;
}
<div class="container4">
<p class="element4">
Drummer and beat producer from Gothenburg, based in Oslo. The beats are
built around Pers drumming, <br />
using samples from a wide variety of genres <br />
mixed with other sounds.
</p>
<img class="element4-2" src="../Images/galgeberg.png" alt="wall2" />
</div>
Couple of problems:
if you want both columns to be 50% width on all screen sizes, you need to set flex:1 1 50% on both the p and the img tags.
if you want the img tag to scale up and down instead of always being it's full size, you need to set width:100%;height:auto on it.
if you want to center the two elements vertically all you need is align-items:center on their container (where display:flex is defined) and not use any vertical padding on them
As a matter of personal preference I would set display:block on both the p and img tags, or better yet wrap them in tags to prevent any weirdness from what styles some browsers could put on them.
Code:
<div class="container4">
<p class="element4">Drummer and beat producer from Gothenburg, based in Oslo. The beats are built around Pers drumming,<br />using samples from a wide variety of genres <br />mixed with other sounds.</p>
<img class="element4-2" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/29841/dog.jpg" alt="wall2" />
</div>
<style>
.container4 {
font-size: 40px;
display: flex;
align-items: center;
gap: 50px;
}
.element4 {
padding-left: 50px;
flex: 1 1 50%;
}
.element4-2 {
padding-right: 50px;
flex: 1 1 50%;
width:100%;height:auto;
}
</style>
Codepen: https://codepen.io/nonsintetic/pen/poWygaY (tested on Safari and Chrome on a mac with latest everything)
Few things, The align item stretch is causing the issue. also you need to make sure that you are diving the 50% gap for each element, third you have set the max-width of the image to maintain the sizing. here is the jsfiddle with responsiveness.
.container4 {
font-family: "Chakra Petch", sans-serif;
font-size: clamp(30px,20vw+1px,40px);
display: flex;
justify-content: space-between;
padding:2em;
}
.element4{
max-width:50%;
margin:auto;
}
.element4-2{
max-width:50%;
margin:auto;
}
.container4 img{
width:100%;
}
<div class="container4">
<p class="element4">
Drummer and beat producer from Gothenburg, based in Oslo. The beats are
built around Pers drumming, <br />
using samples from a wide variety of genres <br />
mixed with other sounds.
</p>
<img class="element4-2" src="https://www.ejin.ru/wp-content/uploads/2017/09/2-2400-696x392.jpg" alt="wall2" />
</div>
I never had problems using flexbox on modern browsers.
I'm assuming there is some typo/error in your css.
Without the entire code, it's hard to know what will and will not work for your specific layout.
Anyways, my approach would be more like:
.container {
font-family: "Chakra Petch", sans-serif;
font-size: 40px;
display: flex;
flex-direction: row; // makes sure it's treated as row
width: 100vw; // 100 viewport width = fills entire viewport width
height: 100%; // take 100% of available space (since you have a header)
justify-content: center;
align-items: center;
}
.page-paragraph {
margin: 0;
padding: 50px; // padding of 50px all around
}
.page-img {
width: 50%; // image is always 50% of available width
margin: 50px;
}
Any reason you are exclusively using classes?
If an element occurs only once, it's smart to give it an id instead.
You can specify an ID with the '#' selector.
Also scratch the break tags if you are going for a fluid layout,
in some cases you might only have the word 'drumming' in a single line.

css display flex not working properly on chrome and safari

I used flexbox properties to make my section look like this:
It works fine on Chrome but I noticed a few differences when I checked firefox and safari.
This is how chrome looks like:
But on Firefox, I am not managing to apply to margin of 1% like I want as the red signal shows:
And on safari, the boxes are all one after the other:
It is a WordPress Site and not live yet. But here is my html structure:
<section id="services">
// here goes the title of the container
<div class="main-container col-lg">
// here go all the box
<div class="services-container">
// this one of the boxes
</div>
</div>
</section>
And the CSS:
#services {
background-image: url("img/Services-background.jpg");
background-color: red;
}
.col-lg {
display: flex;
flex-wrap: wrap;
justify-content: center;
margin: initial;
max-width: 100%;
}
.services-container {
color: #d6d6d6;
margin: 1%;
max-width: 100%;
width: 30%;
}
How Can I make this work on all browsers?
The best way to ensure that flex is working equally on all browsers is to use prefixes.
Here's the chart from MDN showing you the different browser prefixes available for flex box (and general browser support notices)
display: flex;
-webkit-display: flex;
-moz-display: flex;
-ms--display: flex;
I strongly suggest you not use flexbox, but floats instead.
Delete all the flex properties your css should look like this:
#services{
background-image: url(img/Services-background.jpg);
overflow: auto;
}
.services-container {
color: #d6d6d6;
width: 30%;
float: left;
margin: 1%;
}
Then you can add the rest of the styling. It will work on all browsers.
Sometimes the HTML version may be the reason (it was in my case):
I looked for <!DOCTYPE html> at the top of the source code. My HTML turned out to 4.0 something and that was the reason (most probably) that flex did not work. Once that was changed, it worked well.
Good luck...

2 column responsive masonry-like layout without javascript?

I have a number of divs of dynamic height I would like to place into two columns that display immediately after the other, ideally without javascript (and libraries such as packery, masonry etc).
I've begun with display: inline-block jsbin
I've also tried following Easy Masonry Layout With Flexbox to no avail jsbin
I could structure the DOM into separate columns but this isn't ideal as they need to collapse into a single column on mobile.
Of course, simply using inline-block results in an unwanted gap along the lines of this:
EDIT: Updated diagrams to be more clear about desired result - left to right columns with no unwanted gaps
You should set float:left css to all your divs.
<div style="float:left; display:inline-block;">
these divs will be displayed next to each other.
</div>
I hope this will help you.
You can use CSS columns now without worrying too much about browser support. Older IE versions are the only potential blocker, depending on your audience. There are also still quite a few browser quirks to work around, but I've been using them in production for a while now. It's your only real option for a masonry-like layout today, without using JS.
Here is one solution you can use flex for this
CSS
.flex-container {padding: 0; margin: 0; list-style: none; display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; -webkit-flex-flow: row wrap; justify-content: space-around; }
.flex-item {background: tomato; padding: 5px; width: 200px; height: 150px; margin-top: 10px; line-height: 150px; color: white; font-weight: bold; font-size: 3em; text-align: center; }
#fl-item{height:200px;}
And HTML
<ul class="flex-container">
<li class="flex-item" id="fl-item">1</li>
<li class="flex-item">2</li>
<li class="flex-item">3</li>
<li class="flex-item">4</li>
<li class="flex-item">5</li>
<li class="flex-item">6</li>
</ul>
And you can see working Plunker

Table padding in Internet Explorer

I've noticed that Internet Explorer seems to ignore a table's padding. I've tested version 7, 8 and 9.
What is the best workaround? I prefer a workaround that's based purely on CSS than one that involves wrapping tables in <div>s or messing with tags in general.
Try this:
td
{
display: table-cell;
padding: 30px;
border: 1px solid #000000;
}
As seen on jsfiddle.
I have found that this actually works as a fallback for flex box in ie9. And while the original question has nothing to do with CSS flex,and this is probably a repeat, it solved an issue for us, so I will mention it here and hope it helps others.
flex: .selector { display: flex; } and no flex fallback:
.no-flexbox .selector { display: table-cell; padding : 25%; }

Can you do this HTML layout without using tables?

Ok, I had a simple layout problem a week or two ago. Namely sections of a page needed a header:
+---------------------------------------------------------+
| Title Button |
+---------------------------------------------------------+
Pretty simple stuff. Thing is table hatred seems to have taken over in the Web world, which I was reminded of when I asked Why use definition lists (DL,DD,DT) tags for HTML forms instead of tables? Now the general topic of tables vs divs/CSS has previously been discussed, for example:
DIV vs Table; and
Tables instead of DIVs.
So this isn't intended to be a general discussion about CSS vs tables for layout. This is simply the solution to one problem. I tried various solutions to the above using CSS including:
Float right for the button or a div containing the button;
Position relative for the button; and
Position relative+absolute.
None of these solutions were satisfactory for different reasons. For example the relative positioning resulted in a z-index issue where my dropdown menu appeared under the content.
So I ended up going back to:
<style type="text/css">
.group-header { background-color: yellow; width: 100%; }
.group-header td { padding: 8px; }
.group-title { text-align: left; font-weight: bold; }
.group-buttons { text-align: right; }
</style>
<table class="group-header">
<tr>
<td class="group-title">Title</td>
<td class="group-buttons"><input type="button" name="Button"></td>
</tr>
</table>
And it works perfectly. It's simple, as backward compatibile as it gets (that'll work probably even on IE5) and it just works. No messing about with positioning or floats.
So can anyone do the equivalent without tables?
The requirements are:
Backwards compatible: to FF2 and IE6;
Reasonably consistent: across different browsers;
Vertically centered: the button and title are of different heights; and
Flexible: allow reasonably precise control over positioning (padding and/or margin) and styling.
On a side note, I came across a couple of interesting articles today:
Why CSS should not be used for layout; and
Tables vs CSS: CSS Trolls begone
EDIT: Let me elaborate on the float issue. This sort of works:
<html>
<head>
<title>Layout</title>
<style type="text/css">
.group-header, .group-content { width: 500px; margin: 0 auto; }
.group-header { border: 1px solid red; background: yellow; overflow: hidden; }
.group-content { border: 1px solid black; background: #DDD; }
.group-title { float: left; padding: 8px; }
.group-buttons { float: right; padding: 8px; }
</style>
</head>
<body>
<div class="group-header">
<div class="group-title">This is my title</div>
<div class="group-buttons"><input type="button" value="Collapse"></div>
</div>
<div class="group-content">
<p>And it works perfectly. It's simple, as backward compatibile as it gets (that'll work probably even on IE5) and it just works. No messing about with positioning or floats.</p>
<p>So can anyone do the equivalent without tables that is backwards compatible to at least FF2 and IE6?</p>
<p>On a side note, I came across a couple of interesting articles today:</p>
</div>
</body>
</html>
Thanks to Ant P for the overflow: hidden part (still don't get why though). Here's where the problem comes in. Say I want the title and button to be vertically centered. This is problematic because the elements are of different height. Compare this to:
<html>
<head>
<title>Layout</title>
<style type="text/css">
.group-header, .group-content { width: 500px; margin: 0 auto; }
.group-header { border: 1px solid red; background: yellow; overflow: hidden; }
.group-content { border: 1px solid black; background: #DDD; }
.group-header td { vertical-align: middle; }
.group-title { padding: 8px; }
.group-buttons { text-align: right; }
</style>
</head>
<body>
<table class="group-header">
<tr>
<td class="group-title">This is my title</td>
<td class="group-buttons"><input type="button" value="Collapse"></td>
</tr>
</table>
<div class="group-content">
<p>And it works perfectly. It's simple, as backward compatibile as it gets (that'll work probably even on IE5) and it just works. No messing about with positioning or floats.</p>
<p>So can anyone do the equivalent without tables that is backwards compatible to at least FF2 and IE6?</p>
<p>On a side note, I came across a couple of interesting articles today:</p>
</div>
</body>
</html>
which works perfectly.
There is nothing wrong with using the tools that are available to you to do the job quickly and correctly.
In this case a table worked perfectly.
I personally would have used a table for this.
I think nested tables should be avoided, things can get messy.
Just float left and right and set to clear both and you're done. No need for tables.
Edit: I know that I got a lot of upvotes for this, and I believed I was right. But there are cases where you simply need to have tables. You can try doing everything with CSS and it will work in modern browsers, but if you wish to support older ones... Not to repeat myself, here the related stack overflow thread and rant on my blog.
Edit2: Since older browsers are not that interesting anymore, I'm using Twitter bootstrap for new projects. It's great for most layout needs and does using CSS.
Float title left, float button right, and (here's the part I never knew until recently) - make the container of them both {overflow:hidden}.
That should avoid the z-index problem, anyway. If it doesn't work, and you really need the IE5 support, go ahead and use the table.
This is kind of a trick question: it looks terribly simple until you get to
Say I want the title and button to be vertically centered.
I want to state for the record that yes, vertical centring is difficult in CSS. When people post, and it seems endless on SO, "can you do X in CSS" the answer is almost always "yes" and their whinging seems unjustified. In this case, yes, that one particular thing is hard.
Someone should just edit the entire question down to "is vertical centring problematic in CSS?".
In pure CSS, a working answer will one day be to just use "display:table-cell". Unfortunately that doesn't work across current A-grade browsers, so for all that you might as well use a table if you just want to achieve the same result anyway. At least you'll be sure it works far enough into the past.
Honestly, just use a table if it's easier. It won't hurt.
If the semantics and accessibility of the table element really matter to you, there is a working draft for making your table non-semantic:
http://www.w3.org/TR/wai-aria/#presentation
I think this requires a special DTD beyond XHTML 1.1, which would just stir up the whole text/html vs application/xml debate, so let's not go there.
So, on to your unresolved CSS problem...
To vertically align two elements on their center: it can be done a few different ways, with some obtuse CSS hackery.
If you can fit within the following constraints, then there is a relatively simple way:
The height of the two elements is fixed.
The height of the container is fixed.
The elements will be narrow enough not to overlap (or can be set to a fixed width).
Then you can use absolute positioning with negative margins:
.group-header { height: 50px; position: relative; }
.group-title, .group-buttons { position: absolute; top: 50%; }
# Assuming the height of .group-title is a known 34px
.group-title { left: 0; margin-top: -17px; }
# Assuming the height of .group-buttons is a known 38px
.group-buttons { right: 0; margin-top: -19px; }
But this is pointless in most situations... If you already know the height of the elements, then you can just use floats and add enough margin to position them as needed.
Here is another method which uses the text baseline to vertically align the two columns as inline blocks. The drawback here is that you need to set fixed widths for the columns to fill out the width from the left edge. Because we need to keep the elements locked to a text baseline, we can't just use float:right for the second column. (Instead, we have to make the first column wide enough to push it over.)
<html>
<head>
<title>Layout</title>
<style type="text/css">
.group-header, .group-content { width: 500px; margin: 0 auto; }
.group-header { border: 1px solid red; background: yellow; }
.valign { display: inline-block; vertical-align: middle; }
.group-content { border: 1px solid black; background: #DDD; }
.group-title { padding: 8px; width: 384px; }
.group-buttons { padding: 8px; width: 84px; text-align: right; }
</style>
<!--[if lt IE 8]>
<style type="text/css">
.valign { display: inline; margin-top: -2px; padding-top: 1px; }
</style>
<![endif]-->
</head>
<body>
<div class="group-header">
<div class="valign">
<div class="group-title">This is my title.</div>
</div><!-- avoid whitespace between these! --><div class="valign">
<div class="group-buttons"><input type="button" value="Collapse"></div>
</div>
</div>
<div class="group-content">
<p>And it works perfectly, but mind the hacks.</p>
</div>
</body>
</html>
The HTML: We add .valign wrappers around each column. (Give them a more "semantic" name if it makes you happier.) These need to be kept without whitespace in between or else text spaces will push them apart. (I know it sucks, but that's what you get for being "pure" with the markup and separating it from the presentation layer... Ha!)
The CSS: We use vertical-align:middle to line up the blocks to the text baseline of the group-header element. The different heights of each block will stay vertically centered and push out the height of their container. The widths of the elements need to be calculated to fit the width. Here, they are 400 and 100, minus their horizontal padding.
The IE fixes: Internet Explorer only displays inline-block for natively-inline elements (e.g. span, not div). But, if we give the div hasLayout and then display it inline, it will behave just like inline-block. The margin adjustment is to fix a 1px gap at the top (try adding background colors to the .group-title to see).
I would recommend not using a table in this instance, because that is not tabular data; it's purely presentational to have the button located at the far right. This is what I'd do to duplicate your table structure (change to a different H# to suit where you are in your site's hierarchy):
<style>
.group-header { background: yellow; zoom: 1; padding: 8px; }
.group-header:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
/* set width appropriately to allow room for button */
.group-header h3 { float: left; width: 300px; }
/* set line-height or margins to align with h3 baseline or middle */
.group-header input { float: right; }
</style>
<div class="group-header">
<h3>This is my title</h3>
<input type="button" value="Collapse"/>
</div>
If you want true vertical alignment in the middle (ie, if the text wraps the button is still middle-aligned with respect to both lines of text), then you either need to do a table or work something with position: absolute and margins. You can add position: relative to your drop-down menu (or more likely its parent) in order to pull it into the same ordering level as the buttons, allowing you to bump it above them with z-index, if it comes to that.
Note that you don't need width: 100% on the div because it's a block-level element, and zoom: 1 makes the div behave like it has a clearfix in IE (other browsers pick up the actual clearfix). You also don't need all those extraneous classes if you're targeting things a bit more specifically, although you might need a wrapper div or span on the button to make positioning easier.
Do a double float in a div and use the clearfix. http://www.webtoolkit.info/css-clearfix.html Do you have any padding/margin restrictions?
<div class="clearfix">
<div style="float:left">Title</div>
<input type="button" value="Button" style="float:right" />
</div>
<div class="group-header">
<input type="button" name="Button" value="Button" style="float:right" />
<span>Title</span>
</div>
I've chose to use Flexbox, because it made things so much easier.
You basically need to go to the parent of the children you want to align and add display:box (prefixed of course). To make them sit in the sides, use justify-content. Space between is the right thing when you have elements which need to be aligned to the end, like in this case (see link)...
Then the vertical align issue. Because I made the parent of the two elements, you want to align a Flexbox. It's easy now to use align-items: center.
Then I added the styles you wanted before, removed the float from the title and button in the header and added a padding:
.group-header, .group-content {
width: 500px;
margin: 0 auto;
}
.group-header{
border: 1px solid red;
background: yellow;
overflow: hidden;
display: -webkit-box;
display: -moz-box;
display: box;
display: -webkit-flex;
display: -moz-flex;
display: -ms-flexbox;
display: flex;
-webkit-justify-content: space-between;
-moz-justify-content: space-between;
-ms-justify-content: space-between;
-o-justify-content: space-between;
justify-content: space-between;
webkit-align-items: center;
-moz-align-items: center;
-ms-align-items: center;
-o-align-items: center;
align-items: center;
padding: 8px 0;
}
.group-content{
border: 1px solid black;
background: #DDD;
}
.group-title {
padding-left: 8px;
}
.group-buttons {
padding-right: 8px
}
See Demo
I agree that one should really only use tables for tabular data, for the simple reason that tables don't show until they're finished loading (no matter how fast that is; it's slower that the CSS method). I do, however, feel that this is the simplest and most elegant solution:
<html>
<head>
<title>stack header</title>
<style type="text/css">
#stackheader {
background-color: #666;
color: #FFF;
width: 410px;
height: 50px;
}
#title {
color: #FFF;
float: left;
padding: 15px 0 0 15px;
}
#button {
color: #FFF;
float: right;
padding: 15px 15px 0 0;
}
</style>
</head>
<body>
<div id="stackheader">
<div id="title">Title</div>
<div id="button">Button</div>
</div>
</body>
</html>
The button function and any extra detail can be styled from this basic form. Apologies for the bad tags.