1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Really basic PHP array break

Discussion in 'HTML, Graphics & Programming' started by Russinating, 8 Nov 2021.

  1. Russinating

    Capodecina

    Joined: 27 Dec 2005

    Posts: 16,787

    Location: Bristol

    I'm using PHP and an array to print HTML divs in rows of 3s for a grid-layout. The code is basically this, less the array content:

    Code:
    <div class="row ht3" data-aos="fade-up">
    <?php
    $divcount = 0;
    foreach ($work as $value){
    print "$value \n";
    $divcount = $divcount + 1;
    if($divcount % 3 == 0){
    ?>
    </div>
    <div class="row ht3" data-aos="fade-up">
    <?php
    }
    }
    ?>
    </div>
    What I want is for the foreach() to break so that the last row of the grid contains a full 3, rather than 1 or 2, effectively dropping the last 1 or 2 contents of the array.

    I could do a clunky solution where I count the array, divide it by 3, then count the rows as they get created in the foreach() and break it based on that but that seems longwinded.

    What's a neater solution?
     
  2. touch

    Capodecina

    Joined: 28 Oct 2006

    Posts: 12,003

    Location: Sufferlandria

    I would do it by discarding the extra items from the array before looping through it

    while($work.lenth % 3 != 0){
    array_pop($work);
    }
     
  3. Russinating

    Capodecina

    Joined: 27 Dec 2005

    Posts: 16,787

    Location: Bristol

    Looks neat! But:

    Warning: Use of undefined constant lenth - assumed 'lenth' (this will throw an Error in a future version of PHP) in index.php on line 67
    Warning
    : A non-numeric value encountered in index.php on line 67
    Notice
    : Array to string conversion in index.php on line 67

    (Also tried .length as I assume that's a typo!)
     
  4. touch

    Capodecina

    Joined: 28 Oct 2006

    Posts: 12,003

    Location: Sufferlandria

    Sorry, I think it should actually be count instead of length? I'm not super familiar with PHP
     
  5. Russinating

    Capodecina

    Joined: 27 Dec 2005

    Posts: 16,787

    Location: Bristol

    while(count($work) % 3 != 0){
    array_pop($work);
    }

    ...works. So yeah, thanks, perfecto :)
     
  6. ChroniC

    Sgarrista

    Joined: 18 Oct 2002

    Posts: 9,618

    This seems a clunky way to do something that doesn't even require php. Forgive me if I have misunderstood, but what css framework are you using?

    Do you need some sort of gap underneath each 3rd object, is that why you're adding each set of 3 into a new row? With a grid layout that is just blocks of 3, can't you use what column option you have for 3rd? They will just drop onto new lines anyway. Worst case flex-box will do this, with "display:flex; flex-wrap:wrap" on the container div and "width:33%" set on the items.

    else id do this

    <?php
    $i = 1;
    foreach($work as $value) {
    print "$value";
    if($i % 3 == 0) { echo '</div><div class="row ht3" data-aos="fade-up">'; }
    $++;
    } ?>
     
    Last edited: 11 Nov 2021
  7. touch

    Capodecina

    Joined: 28 Oct 2006

    Posts: 12,003

    Location: Sufferlandria

    I dont think it would be that simple to do in pure CSS. If you just add all the elements and set their width to 33% it'll work fine if the number of elements is a multiple of 3 but otherwise you'll still have the problem of the final row having a different number of elements to the previous rows (but they will still be the same size and in alignment).

    I suppose you could always hide the last row using something like:
    .ht3:last-child{display:none;}
    Which would mean the last visible row always contains 3 elements but in some cases you'd also end up hiding a full row of 3 elements when you didn't need to.
     
  8. ChroniC

    Sgarrista

    Joined: 18 Oct 2002

    Posts: 9,618

    The php will do the same thing. It's still going to just stick a new row in every 3rd element. You'd still end up with spare items if the count isn't divisible by 3.
    I don't think the OP mentioned that they wanted a perfect grid, although I did just assume they wanted items in a grid shape.
    If you wanted to solve the last row as random shaped, you could do as you suggested and set the :last-child .item { width: unset; flex-grow: 1; } that should just let them take up the available room.

    I still think css could do all of this.
     
  9. touch

    Capodecina

    Joined: 28 Oct 2006

    Posts: 12,003

    Location: Sufferlandria

    Did you read the OP? :p

    The PHP that we came up with earlier does exactly that - removes any spare items so that the grid always contains a multiple of 3.
     
  10. ChroniC

    Sgarrista

    Joined: 18 Oct 2002

    Posts: 9,618

    Lol. Clearly not, I didn't get that at all.
    I guess the css issue would hide the last row even if it had 3 on it, which isn't ideal, and thus couldn't be achieved without PHP.

    Well ignore everything i've said, it's been a huge waste of time :D
     
  11. Russinating

    Capodecina

    Joined: 27 Dec 2005

    Posts: 16,787

    Location: Bristol

    Haha, thanks anyway @ChroniC. To clear it up the actual page in question is jonesmillbank.com/work.
     
  12. ChroniC

    Sgarrista

    Joined: 18 Oct 2002

    Posts: 9,618

    Cool. Nice site. Only gripe is the page loads speed for me is like 3 or 4s of the spinner. Wouldn't a lazy load of images or posts be better to speed things up.
    Also a massive personal preference from me but I hate animate on scroll on mobile, if you flick a page quickly, it always appears blank before the animation can catch up. I find it very distracting.
     
  13. touch

    Capodecina

    Joined: 28 Oct 2006

    Posts: 12,003

    Location: Sufferlandria

    I think the main problem with the loading speed is the images. The thumbnails in the grid are loaded in at full size 3840px wide but only displayed at around 400px wide. You could replace these with scaled down images which would help loading speed.
    (but check mobile views, too. On smaller screens when the grid falls back to a single column then the images are displayed a but bigger so keep these sizes in mind too when scaling.)
     
  14. Dup

    Capodecina

    Joined: 10 Mar 2006

    Posts: 10,657

    Location: East Lancs

    That page is 30MB!

    All the images on the page are being downloaded before the page displays anything then when you scroll it appear as if they're supposed to be lazy-loaded but clearly not.

    You need to re-size them and run through an optimiser to drop them to 1280 tops (the maximum they're ever displayed at on that page), maybe look into WebP with fallbacks plus genuinely lazy-load them. Nobody should need to wait for the whole page to load. In fact I don't understand the loading animation at all, especially switching between pages on a site you've already loaded. SEO and UX wise it must be hurting you.
     
  15. Russinating

    Capodecina

    Joined: 27 Dec 2005

    Posts: 16,787

    Location: Bristol

    Yeah it's a fair point. It's never really impacted SEO - we're #1 for a few key local search terms - but obviously every little helps. And for UX, for sure, especially those with **** connections. Given what we do though I wouldn't want to go too far with compression, but I should defo look at dropping the res for the gallery images. And I'll be honest, I've never looked at lazy load before but it's on my radar.

    Would you recommend doing it browser-level?
     
  16. ChroniC

    Sgarrista

    Joined: 18 Oct 2002

    Posts: 9,618

    It's not even bad connection. Tried it for the first time on my Mac today, took over 30s to load the page. I'd normally leave after 5.
    Have you made this site totally in PHP? Can detect any sort of CMS on it.

    None of those images are need more than a 400x400 sized picture, and that will still be high quality even at around 250kb, it also slows a browser when it has to resize an image to fit the containing element, which could well be half the problem. Better to make them fairly close to the correct size.
    If you want higher res images per device then you can use the <picture> tag.


    Code:
    <picture>
        <source
          srcset="/media/cc0-images/surfer-1000px.jpg"  media="(min-width: 800px)"
          srcset="/media/cc0-images/surfer-1600px.jpg"  media="(min-width: 1200px)"
          >
        <img src="/media/cc0-images/surfer-500px.jpg" alt="" />
    </picture>
    But, if your not using a CMS then the filling in the sizes dynamically obviously would need to be done manually, meaning you'd have to resize all your images 3 times.
    There are plenty of functions out there that will do it for you, but I have no experience in doing this , so couldn't help.

    In your case though, I would just resize all your square images down to 400x400 and be done with it. 1 of your images is 2.5mb, a few are 1.5mb and most are nearly 900kb. It's a huge amount for a single page.

    You could add this Javascript lazyload library in the head
    Code:
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vanilla-lazyload/17.3.1/lazyload.min.js" integrity="sha512-lVcnjCLGjJTaZU55wD7H3f8SJVi6VV5cQRcmGuYcyIY607N/rzZGEl90lNgsiEhKygATryG/i6e5u2moDFs5kQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    The add this script to the footer or your main.js file.
    Code:
    <script>
    new LazyLoad({
      elements_selector: `.lazy`,
    });
    </script>
    Then on your image tags add the class="lazy" and instead of src="", use data-src=""

    Should work.
     
    Last edited: 22 Nov 2021
  17. Russinating

    Capodecina

    Joined: 27 Dec 2005

    Posts: 16,787

    Location: Bristol

    Thanks @ChroniC. How does the lazyload library work with the above <picture> code with regards to using data-src instead of src? Is data-srcset="" valid?
     
  18. touch

    Capodecina

    Joined: 28 Oct 2006

    Posts: 12,003

    Location: Sufferlandria

    The image is already being compressed to that size. It's displayed at 400px on screen* so whether that happens by you uploading a huge image and the browser displaying it at 400px or you uploading a 400px image and the browser displaying it at full size won't actually make much difference. You can only get 400 pixels of detail in a 400px wide image no matter what you do.

    *not always displayed at 400px, the responsive design means that some smaller screen sizes display larger images so don't just reupload everything at 400px size.
     
  19. ChroniC

    Sgarrista

    Joined: 18 Oct 2002

    Posts: 9,618

    You can do it two ways.
    Code:
    <img
      alt="A lazy image"
      class="lazy"
      data-src="lazy.jpg"
      data-srcset="lazy_400.jpg 400w,
        lazy_800.jpg 800w"
      data-sizes="100w"
    />
    Or

    Code:
     <picture>
      <source media="(min-width: 1200px)" data-srcset="lazy_1200.jpg 1x, lazy_2400.jpg 2x" />
      <source media="(min-width: 800px)" data-srcset="lazy_800.jpg 1x, lazy_1600.jpg 2x" />
      <img alt="A lazy image" class="lazy" data-src="lazy.jpg" />
    </picture>
    Good documentation here.
    https://www.npmjs.com/package/vanilla-lazyload
     
  20. Russinating

    Capodecina

    Joined: 27 Dec 2005

    Posts: 16,787

    Location: Bristol

    Well, thanks @ChroniC, you took me down a path of a much-needed underhaul :D