1

I am using Material-ui-next and trying to create images in a very particular fashion.

   ------  ---------
   |    |  |   | 2 |
   |    |  | 1 |---|
   |    |  |   | 3 |
   ------  ---------

I have had a few fairly odd issues.

1 - 3 appears under 1

2 - 2 and 3 do not fill up their entire space (when highlighted, only half the content space is utilized regardless of image)

3 - sometimes I will get something resembling the below:

   ------  ---------
   |    |  |   | 2 |
   |    |  | 1 |---|
   |    |  |   | 3 |
   |    |  ---------
   ------
in that instance, everything on the right isn't extending all the way down

For your reference, if you follow this link then you will go to the material-ui-next GridList docs. Under Advanced Grid List, you will see one big image and many small ones underneath. My goal is to simply flip that horizontally.

I have attampted the following:

  <GridList cols={4} rows={2}>
  {
    media.map((file, i) => (
      <GridListTile style={{ display: 'flex', flexFlow: 'wrap row' }} cellHeight={200} key={i} cols={i===0 ? 3 : 1} rows={i===0 ? 2 : 1}>
        <img src={file.url} />
      </GridListTile>
    ))
  }
  </GridList>

The above resulted in 3 appearing below 2

  <GridList cols={2} row={2} className={classes.gridList}>
    {
      <GridListTile cellHeight={200} key={1} cols={2} rows={2}>
        <img src={file.url} />
      </GridListTile>
    }
    </GridList>
  </Grid>

  <Grid item xs={12} md={3} style={{padding: '14px', paddingLeft: 0}}>
    <Typography style={{ visibility: 'hidden' }}>a</Typography>
    <GridList>
    {
      user && user.Media &&
      <GridListTile cellHeight={200} style={{paddingBottom: 0}}>
        <img src={file.url} />
      </GridListTile>
    }
    </GridList>
    <GridList>
    {
      user && user.Media &&
      <GridListTile cellHeight={200} key={1} cols={1}>
        <img src={file.url} />
      </GridListTile>
    }
    </GridList>

This solves issue 1 but then 2 and 3 remained.

I have tried to use native flex-box but every time I do the image that is supposed to be larger gets converted to the sizes of the others.

This is the css I have used for flex-box (admittedly little).

gridContainer: {
    display: 'flex',
    flexFlow: 'row',
    justifyContent: 'space-around',
    margin: '3rem 0'
},

EDIT - NEW

The below is working better than anything above. The two small side images working perfectly and will change size with the screen. The large image will not and will stay completely fixed.

New CSS

gridList: {
    transform: 'translateZ(0)',
    display: 'flex',
    justifyContent: 'left',
    alignItems: 'left',
    overflow: 'hidden',
    '& img': {
      flexShrink: 1,
      minWidth: '200%',
      minHeight: '200%'
    }
  },
  gridListSmall: {
    transform: 'translateZ(0)',
    display: 'flex',
    justifyContent: 'left',
    alignItems: 'left',
    overflow: 'hidden',
    '& img': {
      flexShrink: 0,
      minWidth: '100%',
      minHeight: '100%'
    }
  },

New HTML/JSX

       <div cols={2} row={2} className={classes.gridList}>
        {
          <div cellHeight={200} key={1} cols={2} rows={2}>
            <img src={file.url} />
          </div>
        }
        </div>
      </Grid>

      <Grid item xs={12} md={3} style={{padding: '14px', paddingLeft: 0}}>
        <Typography style={{ visibility: 'hidden' }}>a</Typography>
        <div>
        {
          user && user.Media &&
          <div cellHeight={200} style={{paddingBottom: 0}}>
            <img src={file.url} />
          </div>
        }
        </div>
        <div>
        {
          user && user.Media &&
          <div cellHeight={200} key={1} cols={1}>
            <img src={file.url} />
          </div>
        }
        </div>
Brandon
  • 1,447
  • 2
  • 21
  • 41

2 Answers2

2

Keep the source from the example you pointed at Advanced Grid List

And take a look at this line:

<GridListTile 
  key={tile.img}
  cols={tile.featured ? 2 : 1}
  rows= {tile.featured ? 2 : 1}>

All the featured images occupy 2 column by 2 rows.

You want your featured images to be 1 column by 2 rows, so what you have to do is to change this cols={tile.featured ? 2 : 1} to this cols={tile.cols || 1}.

You can specify how many columns your Grid List has:

<GridList cols={2}>

You can set the cell height:

<GridList cellHeight={160}>

And you can change the properties of the entire grid:

const styles = theme => ({
  gridList: {
    width: 500,
    height: 450,
  }
});

A more flexible way will be to set rows to be rows={tile.rows || 1}.

Now, you can control each image how many columns and rows can occupy

const tileData = [
{
    img: image,
    title: 'Image' // no rows or columns means 1x1
},
{
    img: image,
    title: 'Image',
    rows: 2 // 2 rows 1 column
},
{
    img: image,
    title: 'Image',
    cols: 2 // 1 rows 2 columns
},
{
    img: image,
    title: 'Image',
    rows: 2,
    cols: 2 // 2 rows & 2 columns
},

ANSWER TO YOUR NEW EDIT

I think you mixed your elements badly. The structure of the grid is:

  • Grid-container = a div with classes.root
    • GridList = <GridList> with classes.gridList and cellHeight prop
      • GridListTile = <GridListTile> with cols and rows
        • Your Image
        • Some other content
      • GridListTile = <GridListTile> with cols and rows
        • Your Image
        • Some other content

<GridListTile> determines the size required for your image and is the only one that needs to be filled with an image. This can be 1x1, 1x2, 2x1...

In your code I see div with cols and rows, div with cellHeight, the structure is incomplete (I can't see the entire tree)... i can't make any sense of that.


Questions

  • Are you using the component you referred in your example?
  • Do you need more then those 3 images?

Hint

The component you referred does not guarantee exact order of images, they are reordered to fill all cells.

Valentin
  • 43
  • 5
  • I got it to list appropriately, so thanks. I was wondering if you had any ideas why the side images aren't sized appropriately? I double the size of the first image, two normal sized ones at the side but they don't stretch out as far out as they should. – Brandon Apr 14 '18 at 21:20
  • 1
    @Brandon - A preview will help. Some pointers, the grid is made out of squares, your images must be squares... Take a look at [How can I fill a div with an image while keeping it proportional? ](https://stackoverflow.com/questions/14142378/how-can-i-fill-a-div-with-an-image-while-keeping-it-proportional) – Valentin Apr 14 '18 at 21:25
  • That link was perfect, I made huge progress with it. The new situation is very very close to the end goal. The 2 side images fit perfectly and are properly sized. However, the large image is different. It's sizing isn't dynamic and so if I change the screen, it will not grow/shrink. Added a new code example for the working ish version in the question – Brandon Apr 14 '18 at 21:59
  • 1
    I think you need this [A Complete Guide to Flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) – Valentin Apr 15 '18 at 02:39
1

In creating this answer, I used the advice posted in the question by Valentin and the comments on the post. I ended up abandoning GridList all together and instead just used Flexbox.

html/jsx

            <Grid item xs={12} md={8} style={{paddingRight: 0}}>
              <Typography type="body2">Media</Typography>

                <div>
                {
                  <div className={classes.gridListContainer}>
                    <div className={classes.gridList} style={{width: '70%'}}>
                      <img
                        src={media.url[0]}
                        alt={media[0].name}
                      />
                    </div>
                    <div className={classes.gridListSmall} style={{width: '30%'}}>
                      <img
                        src={media.url[1]}
                        alt={media[1].name}
                      />
                      <img
                        src={media.url[2]}
                        alt={media[2].name}
                      />
                    </div>
                  </div>
                }
                </div>

css

  gridListContainer: {
    display: 'flex',
    flexFlow: 'row'
  },
  gridList: {
    transform: 'translateZ(0)',
    alignItems: 'stretch',
    overflow: 'hidden',
    '& img': {
      width: '100%',
      height: '100%',
    }
  },
  gridListSmall: {
    transform: 'translateZ(0)',
    // flexFlow: 'column',
    justifyContent: 'left',
    alignItems: 'stretch',
    overflow: 'hidden',
    '& img': {
      flexShrink: 0,
      height: '50%',
      verticalAlign: 'middle'
    },
    '& div img': {
      flexShrink: 0,
      height: '50%',
      verticalAlign: 'middle',
      content: 'words'
    }
  }

It creates the perfect shape that I desired as below. It is only supposed to house 3 images, so that's why I was just calling the index.

   ---------
   |   | 2 |
   | 1 |---|
   |   | 3 |
   ---------
Brandon
  • 1,447
  • 2
  • 21
  • 41