Search code examples
htmlcssinternet-explorer-11internet-explorer-10grid-layout

IE11: how to make two-column grid layout that the second column would fill both or one column, depending on whether the first column is displayed


What I want to achieve, is to have two-column grid layout that behaves like this:

if display property of col 1 set to inline - layout should be rendered as follows:

+------+--------------+
|      |              |
|      |              |
|  c   |      c       |
|  o   |      o       |
|  l   |      l       |
|      |              |
|  1   |      2       |
|      |              |
|      |              |
+------+--------------+

in case if display property of col 1 is set to none - col 2 should occupy both columns:

+---------------------+
|                     |
|                     |
|          c          |
|          o          |
|          l          |
|                     |
|          2          |
|                     |
|                     |
+---------------------+

In Chrome and Firefox, I was able to achieve it via following CSS:

#content {
  display: grid;
  grid-template-columns: 15% minmax(85%, 1fr);
}

.col-1 {
  background: #D2691E;
  /* display: none; */
  grid-row-start: 1;
  grid-row-end: 1;
}

.col-2 {
  background: #191970;
  grid-row-start: 1;
  grid-row-end: 1;
  grid-column-start: auto;
  grid-column-end: span 2;
}

Demonstration on JSFiddle


Though, I need the same to work in IE11, and it gets trickier here. I have read this and looked through this one, articles on grid implementation in IE10 and IE11.

col 1 will eventually be a menu, so I've prepared a demo with button that intended to hide/show it via toggling the display property (which works as expected in Chrome and Firefox and doesn't work in IE11):

function toggleDisplay() {
	var menu_div = document.getElementById('menu');
  if (menu_div.style.display === '' || menu_div.style.display === 'none') {
  	menu_div.style.display = 'inline'
  } else {
  	menu_div.style.display = 'none'	
  }
}
#content {
  display: -ms-grid;
  display: grid;
  
  -ms-grid-columns: 15% minmax(85%, 1fr);
  grid-template-columns:  15% minmax(85%, 1fr);
  
  -ms-grid-rows: 1fr;
  
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
}


.menu {
  background: #D2691E;
  display: none;
  
  -ms-grid-row: 1;
  grid-row-start: 1;
  
  -ms-grid-row-span: 1;
  grid-row-end: 1;

}

.content-area {
  background: #191970;
  
  -ms-grid-row: 1;
  grid-row-start: 1;
  
  -ms-grid-row-span: 1;
  grid-row-end: 1;
  
  -ms-grid-column: 2;
  grid-column-start: auto;
  
  -ms-grid-column-span: 2;
  grid-column-end: span 2;
}
<body>
<div id='content'>
<div class='menu' id='menu'></div>
<div class='content-area'>
<button onclick=toggleDisplay() >Show/hide 'display:none'</button>
</div>
</div>
</body>

Code above on JSFiddle

I have also tried different method of toggling 'menu' - via moving it outside the view, with the same result (works in Chrome, Firefox not in IE11, though it toggles the menu in IE, at least):

function toggleLeft() {
  var menu_navigation = document.getElementById('menu');
  if (menu_navigation.style.position === 'fixed' || menu_navigation.style.position === '') { 
    open();
    stopAnimation();
  } else {
    close();
  }
}

function close() {
  var menu_navigation = document.getElementById('menu');
  if (menu_navigation.style.position !== 'fixed') {
    menu_navigation.style.position = 'fixed';
    menu_navigation.style.left = '-15%';
    menu_navigation.style.witdh= '100%';
    menu_navigation.style.height = '100%';
  }  
}

function open() {
  var menu_navigation = document.getElementById('menu');
  if (menu_navigation.style.position !== 'relative') {
    menu_navigation.style.position = 'relative';
    menu_navigation.style.left = '0';
    menu_navigation.style.widh = 'auto';
    menu_navigation.style.height = 'auto';
  }
}
#content {
  display: -ms-grid;
  display: grid;
  
  -ms-grid-columns: 15% minmax(85%, 1fr);
  grid-template-columns:  15% minmax(85%, 1fr);
  
  -ms-grid-rows: 1fr;
  
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
}


.menu {
  background: #D2691E;
  position: fixed;
  left: -15%;
  height: 100%;

  -ms-grid-row: 1;
  grid-row-start: 1;
  
  -ms-grid-row-span: 1;
  grid-row-end: 1;

}

.content-area {
  background: #191970;
    
  -ms-grid-row: 1;
  grid-row-start: 1;
  
  -ms-grid-row-span: 1;
  grid-row-end: 1;
  
  -ms-grid-column: 2;
  grid-column-start: auto;
  
  -ms-grid-column-span: 2;
  grid-column-end: span 2;
  
}
<body>
<div id='content'>
<div class='menu' id='menu'></div>
<div class='content-area'>
<button onclick=toggleLeft() >Show/hide 'left: -15%'</button>
</div>
</div>

</body>

Code above on JSFiddle


I have tried setting -ms-grid-column to auto for first (JSFiddle) and second (JSFiddle) (I guess this one is as close as I could get to the required result) examples above, though desired result still not achieved.

My questions are:

  1. What is the recipe to achieve desired grid layout in IE11, with plain CSS (i.e. without using pre-processors etc.)?
  2. Is grid a good approach to use giving that I need an IE11 support, or some other approach is advised (if so, what might it be)?

Solution

  • You could use the attribute selector to assign styling to the .content-area element:

    .content-area{
        grid-column-start: 1;
    }
    #menu[style="display: block"] + .content-area{
        grid-column-start: auto;
    }
    

    Or, since you're already applying inline styling with JS, you could add and remove the inline grid styling on the content-area element in your open and close functions.

    If this is a general question on using a grid alternative on IE11 - you could look at the modernizr JS library, and use an alternative table layout styling if the browser does not support css-grid.