3

Let's say you want to display elements (like little cards), and you want them to display like this :

First Display : First display

Second Display : Second display

In a nutshell : always fill full width of the container, wrapping, keeping a minimum fixed size, and of course fill the rows with the maximum cards possible.

Consequently, we can already say that:

  • Fixed width are not an option because it will not fill the full width of the container
  • Width in percent won't work because you can't add more tiles to the same line without making an extra media query (can be very boring and this is not scalable at all if you want one day to change the content and the minimum width of the cards)

My first though was about flexbox, it ended up like that :

Just with flexbox CSS

You can see a jsfiddle here to see the code.

We can notice the first line is perfect ! However, if independently of how many lines there are, if the last line doesn't have the same number of elements than the others, it will not display well. (ie stick to the left).

It is normal considering how flex-grow works. But then how to create the effect ?

My solution was to create a custom directive (I work with Angular), it works pretty well (my first images are displayed like that thanks to it.

Here is the directive code :

(function () {

'use strict';

angular.module('app')

    .directive('flexGrowConsistent', function ($window, $document) {

            var directive = {};
            directive.restrict = 'A';

            directive.link = function (scope, elements, attrs) {

                $document.ready(onResize);

                function onResize() {

                    //container width
                    var cw = elements[0].parentElement.offsetWidth;
                    // first element width
                    var w = elements[0].parentElement.firstElementChild.offsetWidth;

                    if (isWrapped(w, cw, scope.$index)) {
                        elements.css({
                            maxWidth: w + 'px'
                        });
                    }

                }

                /*
                 Tell if an element is wrapped given element width, container width and index
                 Take care of the incertainty from javascript with the -0.5
                 */
                function isWrapped(w, cw, index) {
                    return ((w - 0.5) * (index + 1) > cw) && index > 0;
                }

                function cleanUp() {
                    angular.element($window).off('resize', onResize);
                }

                angular.element($window).on('resize', onResize);

                scope.$on('$destroy', cleanUp);

            };

            return directive;
        }
    );
})();

My question is : is there a way to do this with pure CSS ?. I really dislike to use Javascript for a pure display purpose.

If you have propositions to improve the directive, they are welcome as well.

Yangshun Tay
  • 49,270
  • 33
  • 114
  • 141
Alburkerk
  • 1,564
  • 13
  • 19
  • One option: Add several invisible flex items at the end. https://jsfiddle.net/o30p1a5y/2/ – Michael Benjamin Apr 28 '17 at 01:52
  • Another option, CSS Grid Layout: https://jsfiddle.net/o30p1a5y/3/ (Full support in Chrome, FF and Safari. No support in IE / Edge yet.) – Michael Benjamin Apr 28 '17 at 01:59
  • 1
    Even though it's a duplicate, it is a very well written question. I wish more of the questions were done like this ! – vals Apr 28 '17 at 07:23
  • @vals As I already commented under Michael_B's answer on the original question, the answer there has a small problem: one needs about a full hour to read everything linked. When dealing with the above issue, most people want something that can be understood and applied in minutes. – tao Apr 28 '17 at 10:09
  • 1
    @Michael_B, for you first option, it works as well but one need to insert elements. So if your elements are generated with javascript (ng-repeat for instance), one need to estimate the maximum number of tiles fittable in the container (so container should have fixed width if the screen goes too big, but that's standart anyway), and add that much "useless" tiles and put this number in the css property. Very elegant ! CSS Grid Layout seems awesome thought, should be the future answer in a few months. – Alburkerk Apr 28 '17 at 13:54

0 Answers0