Search code examples
jquerycssmedia-queriescss-grid

Media query doesn't execute with matchMedia


This code works quite correctly with two media queries, with the additional action of some jQuery. But I need to refresh the page to make one of the two media queries work.

The role of the jquery is to add two div's in a media query to get a two columns grid (all pictures on the left, title and text on the right). In the other one, without the div's I'm able to rearrange the elements: title, then 1st image, then text, then the rest of the images.

Can't understant why I have to refresh the page manually to get a correct result. Could it be a listener problem? Or is there a better way to achieve my responsive requirements?

var mql = window.matchMedia('(min-width:840px)');

function testState(e) {
  if (e.matches) {
    $("body").css("background-color", "lightgreen"); // for debug
    $(".a").wrapAll("<div class='illus'></div>");
    $(".b").wrapAll("<div class='aside'></div>");
  } else {
    $("body").css("background-color", "lightblue"); // for debug
  }
}

//testState(mql); removed as suggested. No use.
mql.addListener(testState);
.nom {
  grid-area: nom;
}

.texte {
  grid-area: texte;
}

.top {
  grid-area: top;
}

.down {
  grid-area: down;
}

@media (min-width: 450px) and (max-width: 840px) {
  .content {
    display: grid;
    width: 90%;
    margin: 12px auto 0 auto;
    grid-template-columns: auto;
    grid-template-rows: auto;
    grid-template-areas: "nom" "top" "texte" "down";
  }
  .illus img {
    width: 100%;
  }
}

@media (min-width: 840px) {
  .content {
    display: grid;
    grid-template-columns: 58.3333333333% 41.6666666667%;
    max-width: 954px;
    margin: 12px auto 12px auto;
    grid-template-areas: "illus aside";
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="content">
  <div class="top a">
    <p><img src="http://via.placeholder.com/545x399"></p>
  </div>
  <div class="down a">
    <p><img src="http://via.placeholder.com/545x399"></p>
  </div>
  <div class="nom b">
    <h1>A title here</h1>
  </div>
  <div class="texte b">
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean eget mi in purus pellentesque vestibulum vitae quis lacus. Duis gravida mattis lectus quis tincidunt.</p>
    <p>Aenean sed nibh arcu. Nullam cursus, felis sed blandit congue, tellus diam interdum purus, in molestie justo nisi sit amet mi. Vestibulum laoreet neque sed porttitor semper. Suspendisse justo quam, facilisis a maximus id, pharetra vitae velit. Cras
      viverra rutrum libero ac rhoncus.</p>
  </div>
</div>


Solution

  • Your JS seems to be messed up as the <div class='illus'></div> is getting looped inside itself, every time you resize the window, which then breaks your layout.

    I don't think your requirement needs a JS solution as it can be achieved by CSS itself.

    I have rewritten the below block inside the media query @media (min-width: 840px) {}

    .content {
      display: grid;
      max-width: 954px;
      margin: 12px auto;
      grid-template-areas:
        "top nom"
        "top  texte"
        "top  ."
        "down .";
    }
    

    CODEPEN

    Hope this helps. Please let me know.