Really basic PHP array break

Soldato
Joined
27 Dec 2005
Posts
17,281
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?
 
Soldato
OP
Joined
27 Dec 2005
Posts
17,281
Location
Bristol
I would do it by discarding the extra items from the array before looping through it

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

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!)
 
Soldato
Joined
18 Oct 2002
Posts
10,042
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:
Soldato
Joined
28 Oct 2006
Posts
12,456
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.
 
Soldato
Joined
18 Oct 2002
Posts
10,042
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.
 
Soldato
Joined
28 Oct 2006
Posts
12,456
Location
Sufferlandria
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

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.
 
Soldato
Joined
18 Oct 2002
Posts
10,042
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
 
Soldato
Joined
18 Oct 2002
Posts
10,042
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.
 
Soldato
Joined
28 Oct 2006
Posts
12,456
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.)
 

Dup

Dup

Soldato
Joined
10 Mar 2006
Posts
11,225
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.
 
Soldato
OP
Joined
27 Dec 2005
Posts
17,281
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?
 
Soldato
Joined
18 Oct 2002
Posts
10,042
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:
Soldato
Joined
28 Oct 2006
Posts
12,456
Location
Sufferlandria
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.

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.
 
Soldato
Joined
18 Oct 2002
Posts
10,042
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?

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
 
Back
Top Bottom