swiper icon indicating copy to clipboard operation
swiper copied to clipboard

CSS Grid + Swiper Wrapper - wrong width calculated

Open edwardjosephbennett opened this issue 6 years ago • 36 comments

This is a (multiple allowed):

  • [x] bug

  • [ ] enhancement

  • [ ] feature-discussion (RFC)

  • Swiper Version: 4.4.2 from CDNJS

  • Platform/Target and Browser Versions: Latest Chrome on macOS (confirmed issue is happening in Latest Safari also)

  • Live Link or JSFiddle/Codepen or website with isssue: https://codepen.io/anon/pen/pqJBWX (Also raised with others: https://codepen.io/meredevelopment/pen/yorRMm and here on your forums: http://idangero.us/swiper/forum/#!/?css%20grid)

What you did

A basic CSS grid setup with 3 columns setup on a wrapper. Carousel is set up within the 3rd column with a width of 1fr (which should take up 1fr of the remaining space of the max-width container). For code example see codepen showing issue. Code is direct replica of code in my development build.

Expected Behavior

Swiper wrapper is to take up the remaining space of the container instead of overflowing with the correct slidesPerView visible

Actual Behavior

Swiper wrapper is overflowing, with slidersPerView being ignored. Wrapper is showing width of entire width of elements.

edwardjosephbennett avatar Dec 12 '18 09:12 edwardjosephbennett

In such layout, there is no clear way in this case to detect available "cell" width -> so swiper can't calculate its own and slides size. You can fix this current layout but changing width: 100vw on .carousel or by using flex instead of grid

nolimits4web avatar Dec 14 '18 18:12 nolimits4web

I had a similar issue and found a solution.

You can prevent Swiper from overflowing by adding an overflow: hidden to the parent element (in your case the .wrapper).

And there was also an issue with your grid column setup. .sidebar should have a value of 1 / 2 and .carousel a value of 2 / 3.

I updated your Codepen example: https://codepen.io/anon/pen/MdmxNp

mxwendt avatar May 17 '19 09:05 mxwendt

Almost a year later and grid is a best practice. It would really help if this issue would not exist anymore. :)

The fix from https://github.com/nolimits4web/swiper/issues/2914#issuecomment-493384617 worked like a charm nonetheless!

And of course, thank you for swiper, it works really well, and kudos for the good docs!

ankedsgn avatar Oct 22 '19 16:10 ankedsgn

I had a similar issue and found a solution.

You can prevent Swiper from overflowing by adding an overflow: hidden to the parent element (in your case the .wrapper).

And there was also an issue with your grid column setup. .sidebar should have a value of 1 / 2 and .carousel a value of 2 / 3.

I updated your Codepen example: https://codepen.io/anon/pen/MdmxNp

Your solution only works if you set width of some column in 'px'. If columns are set in 'fr' swiper takes all the space and goes into infinity (I have 6-digit numbers in 'translate3d' property of the slides)

suxscribe avatar Dec 10 '19 14:12 suxscribe

At the very least, there should be a "Gotchas" section, or something to that effect added to the documentation that notes this blatant issue. I can imagine many people, like myself, pulled their hair out for far, far too long thinking something was wrong with our setup.

In my case, it was a basic flex layout. Adding overflow: hidden to the parent did fix the issue immediately.

ckihneman avatar Jan 03 '20 08:01 ckihneman

I got the same issue and the overflow: hidden trick doesn't work. I think the problem is similar to what @suxscribe described. I set the layout using fr, not px.

This is my screenshot: https://prnt.sc/ry8y59

rilwis avatar Apr 13 '20 07:04 rilwis

+1

vampics avatar May 27 '20 09:05 vampics

Still happening... Swiper goes bonkers if it's in a Grid with FR units.

When changing grid-template-columns to percentage instead fr, it works, but makes the "grid gaps" calculation more tedious this way.

migueltrias avatar May 28 '20 11:05 migueltrias

Still happening... Swiper goes bonkers if it's in a Grid with FR units.

When changing grid-template-columns to percentage instead fr, it works, but makes the "grid gaps" calculation more tedious this way.

Thank you, helped a lot.

const-int avatar Aug 14 '20 21:08 const-int

+1

kobekoto avatar Aug 17 '20 07:08 kobekoto

Have there been any other fixes? This thread was created on Swiper 4.2.2, but I'm getting similar painful behavior with SwiperJS v6.1.2 & CSS Grid.

In some scenarios, Swiper disregards the grid (as if it has been absolutely positioned). In some scenarios, Swiper will not resize responsively (i.e,. always the max-width of the grid child it's in), even within a breakpoint. Setting overflow:hidden does not fix the issue, and unluckily, we are tied to the fr units. It's one of grid's by-design features to automatically calculate the viewport in fractional units.

I wish we could use flexbox in our layout, but the site is quite deeply integrated in grid. I agree with @ckihneman: if CSS grid incompatibilities are present in the stable release, it should be noted somewhere in the documentation. Grid is a first-class citizen of CSS, at least since early 2017.

The only reliable solution I've found: very carefully limiting the nesting of any SwiperJS element, even divs with zero CSS set. I can get, at most, exactly grid -> grid child -> swiper element. Anything more destroys the layout.

tiadaguru avatar Aug 22 '20 05:08 tiadaguru

I thought overflow is working but it doesnt seem to work, breakpoints get messed up. Is there any way to tackle the fr grid problem? ..... This issue is related to back to 2018 https://github.com/nolimits4web/swiper/issues/2606

aomini avatar Aug 30 '20 11:08 aomini

Works for me like this:

/** @jsx jsx */
import { jsx, Grid } from '@chakra-ui/core';
import Swiper from 'react-id-swiper';

function CarouselGrid() {

    const params = {
      navigation: {
        nextEl: '.swiper-button-next',
        prevEl: '.swiper-button-prev',
      },
    }

    return (
      <Grid gridTemplateColumns="1fr 3fr">
        <div>
          Col Left
        </div>
        <div sx={{ width: '100%', overflow: 'hidden'}}>
          <div sx={{
            '.swiper-container': {
              width: '100%'
            }
          }}>
            <Swiper {...params}>
              <div sx={{ bg: 'gold' }}>Slide #1</div>
              <div sx={{ bg: 'red' }}>Slide #2</div>
            </Swiper>
          </div>
        </div>
      </Grid>
    )
  }

arnaudjnn avatar Sep 09 '20 04:09 arnaudjnn

instead of 'auto' in grid-column definition, you can use 'minmax(0, auto)'. the column width gets calculated in pixel, so the swiper calculates its width correctly.

uldo avatar Dec 11 '20 13:12 uldo

My workaround to solve this problem for a single-slide slider that placed inside flex item.

.swiper-slide {
    width: 100% !important;
}

Tested in Swiper 6.4.8

mintbird avatar Jan 23 '21 06:01 mintbird

Just to contribute to the catalog of workarounds: in my case I was using only a single column in the grid, so I instead of using the default value for grid-template-columns, I explicitly set it to grid-template-columns: 100%; and it worked wonders, thank you guys ;)

vhoyer avatar Feb 05 '21 15:02 vhoyer

One more workaround to add, as I've noticed something specific. If I have a 2-column grid (using grid-template-columns: 1fr 1fr), the crucial part is that the immediate child in the column must have overflow: hidden. Then, Swiper will calculate its width correctly no matter how far nested it is.

  • container (grid, two columns)
    • div (100% width, overflow hidden)
      • div
        • div
          • swiper

If the immediate child of the column is not set to overflow hidden, the width won't be calculated correctly

This will break:

  • container (grid, two columns)
    • div
      • div
        • div (100% width, overflow hidden)
          • swiper

dungle-scrubs avatar Mar 01 '21 03:03 dungle-scrubs

@dungle-scrubs That looks like something that might work for me. Just need on some more info on this. I will need to have something like this in order for swiper to calculate thing right:

  • container (grid, grid tempate columnd 1fr 1fr)
  • div (grid column span 1, 100% width, overflow hidden)
  • swiper

or is it more like this:

  • container (grid, two columns)
  • div (grid column span 1)
  • div (100% width, overflow hidden)
  • swiper

Janchey avatar Mar 11 '21 21:03 Janchey

@dungle-scrubs That looks like something that might work for me. Just need on some more info on this. I will need to have something like this in order for swiper to calculate thing right:

  • container (grid, grid tempate columnd 1fr 1fr)
  • div (grid column span 1, 100% width, overflow hidden)
  • swiper

or is it more like this:

  • container (grid, two columns)
  • div (grid column span 1)
  • div (100% width, overflow hidden)
  • swiper

I believe that the second one you mentioned will break. For me, the immediate grid-child must have the overflow: hidden property, but I'm not sure why it's behaving that way.

Have you had any luck?

dungle-scrubs avatar Mar 16 '21 11:03 dungle-scrubs

@dungle-scrubs That looks like something that might work for me. Just need on some more info on this. I will need to have something like this in order for swiper to calculate thing right:

  • container (grid, grid tempate columnd 1fr 1fr)
  • div (grid column span 1, 100% width, overflow hidden)
  • swiper

or is it more like this:

  • container (grid, two columns)
  • div (grid column span 1)
  • div (100% width, overflow hidden)
  • swiper

I believe that the second one you mentioned will break. For me, the immediate grid-child must have the overflow: hidden property, but I'm not sure why it's behaving that way.

Have you had any luck?

Yes I did. It was a bit different for me. Parent of a slider had to be of width: 100%.

Janchey avatar Mar 17 '21 13:03 Janchey

Right now solution is using minmax(0, 1fr) instead of 1fr.

levazver avatar Mar 30 '21 15:03 levazver

It's useless to swiper if it doesn't work with grid very well. Using overflow: hidden is a hack and a solution. Swiper is good on desktop when using display: grid but when doing responsive it doesn't work very well

aaronchristian99 avatar Jun 25 '21 19:06 aaronchristian99

For me, it worked to wrap the slider with an additional display: grid element and set swiper-container to 100% width. codepen as demo: https://codepen.io/_Mellow/pen/KKmRwzw

janekth avatar Jul 29 '21 20:07 janekth

Solo para contribuir al catálogo de soluciones: en mi caso, estaba usando solo una columna en la cuadrícula, así que en lugar de usar el valor predeterminado para grid-template-columns, lo configuré explícitamente grid-template-columns: 100%;y funcionó de maravilla, gracias chicos;)

Very thanks! its work!

francosalcedo avatar Aug 19 '21 09:08 francosalcedo

I had 2 different scenarios, both kind of relating to what I raised in #4993

Scenario 1

Parent element with display grid and 1 column. Swiper deep nested inside of it.

.parent {
  display: grid;
  grid-template-rows: 16px;
}

The problem here across all browsers was that swiper didn't calculate the width properly so each slide was causing a horizontal scroll by pushing the container. To solve it I also added grid-template-columns: 100%; to the .parent.

Another fix I did for this before was to wrap swiper in another grid and that seemed to do the trick. But that has an issue that I will explain bellow.

Scenario 2

Parent element with display grid and multiple columns. Swiper nested 2 levels down in the .col element.

.parent {
  display: grid;
  grid-template-rows: repeat(var(--rows, 1), 1fr);
  grid-template-columns: repeat(var(--columns, 12), 1fr);
  gap: var(--gap, 16px);
}

.parent .col {
  grid-column: auto/span 6;
}

In this case Chrome is fine, but on Firefox Swiper will grow to infinity without stoping. To fix this I had to change the template columns to grid-template-columns: repeat(var(--columns, 12), minmax(0, 1fr));.

Initially to solve this issue was to disable the resize observer in settings. Seems that the observer triggers all the time.

radum avatar Sep 23 '21 15:09 radum

At the very least, there should be a "Gotchas" section, or something to that effect added to the documentation that notes this blatant issue. I can imagine many people, like myself, pulled their hair out for far, far too long thinking something was wrong with our setup.

In my case, it was a basic flex layout. Adding overflow: hidden to the parent did fix the issue immediately.

Thank you for this info! i am wondering why this issue is unfixed sience 3 years :D

SvenBudak avatar Dec 15 '21 01:12 SvenBudak

This https://youtu.be/mlmADytUiiw?list=PLGhijupHuLxJ4zJCUJcaLwEQSvQKdq-ta&t=504 explains what is happening and why is by design.

radum avatar Dec 15 '21 09:12 radum

++ Suffer the problem with display: flex

px2code avatar Feb 02 '22 19:02 px2code

wasted hours until found the display grid on parent was growing swiper width and some times height to infinity. Used this to fix it but feels scared what if people get that bug in their browser or device for whatever reason

display: grid; grid-template-columns: minmax(0, 1fr);

mbcod3 avatar Feb 25 '22 12:02 mbcod3

Is not a bug, that is how the browser works. It was a learning experience for me also.

radum avatar Feb 25 '22 13:02 radum