1

I have multiple elements with different types of display like .inlineBlock{display:inline-block} or .flex{display:flex} etc. and I have used them like below:

<div class="inlineBlock desktopOnly"></div>
<div class="inlineBlock mobileOnly"></div>
<div class="flex desktopOnly"></div>
<div class="flex mobileOnly"></div>

Some elements should be only visible on desktop and some should be visible just in small screens. So I have defined two media rules:

@media all and (max-width:768px){
    .desktopOnly{
        display:none;
    }

    .mobileOnly{
         display: what??????
     }
}

@media all and (min-width:768px){
    .mobileOnly{
        display:none;
    }

    .desktopOnly{
         display: what??????
     }
}

As you see I don't know how to recover the original display type if element so It fallback to its original display type when media changes? Do I need to redefine any class one-by-one in media rules? is there a general way to handle all elements at once (preferably a CSS only solution)?

Ali Sheikhpour
  • 10,475
  • 5
  • 41
  • 82
  • 2
    You don't need to redefine the the elements. When they are not display: none; and they aren't if the media query doesn't apply to them they will have the properties you defined in your "normal" css. Imho you can completely delete the "what????" part and will achieve exactly what you want to achieve. – MaZoli Mar 09 '20 at 10:45
  • You can use display:inherit; .Inherit property removes all the properties applied before and places the element in normal state. – Hardi Shah Mar 09 '20 at 10:47

2 Answers2

2

Use CSS variables. You make the fallback value the display you want and by setting the variable to none or initial you set/reset the value of the fallback.

Example:

.box {
  height: 50px;
  background: red;
  display: var(--d, flex);
}

@media all and (max-width:800px) {
  .box {
    --d: none; /* we hide it here*/
  }
}

@media all and (max-width:400px) {
  .box {
    --d: initial; /* we show it again here*/
  }
}
<div class="box"></div>

For many elements you can do this at root level:

div[class] {
  height: 50px;
  margin: 5px;
}

.block {
  display: var(--d, block);
  background: red;
}

.flex {
  display: var(--d, flex);
  background: green;
}

.grid {
  display: var(--d, grid);
  background: blue;
}

@media all and (max-width:800px) {
   :root {
    --d: none;
  }
}

@media all and (max-width:400px) {
   :root {
    --d: initial;
  }
}
<div class="flex"></div>
<div class="grid"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="grid"></div>

Considering your example:

div[class] {
  height: 50px;
  min-width:100px;
  margin: 5px;
  background:red;
  color:#fff;
  font-size:30px;
}

.flex {
  display:var(--d,flex);
}
.inlineBlock {
  display:var(--d,inline-block);
}

@media all and (max-width:768px) {
  .desktopOnly {
    --d: none;
  }
  .mobileOnly {
    --d: initial;
  }
}

@media all and (min-width:768px) {
  .mobileOnly {
    --d: none;
  }
  .desktopOnly {
    --d: initial
  }
}
<div class="inlineBlock desktopOnly">Destop</div>
<div class="inlineBlock mobileOnly">Mobile</div>
<div class="flex desktopOnly">Destop</div>
<div class="flex mobileOnly">Mobile</div>

Related question for more details:

How to store inherit value inside a CSS custom property (aka CSS variables)?

CSS custom properties (variables) for box model

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • Thank you. I also upvoted the answer as you defined two steps 800 and 400 pixels because a simple answer is just to leave the element to fallback to initial without defining a media rule (when there are only two conditions). But your answer shows how to force it to react in multiple conditions. – Ali Sheikhpour Mar 09 '20 at 11:17
  • While this solution works as expected, there is no need to use 'custom variables' as the `@media` Queries come after the initial definition of `.flex` and `.inlineBlock`. Putting only `desktopOnly: none` in `@media all and (max-width:768px)` and `mobileOnly: none` in `@media all and (min-width:768px)` will suffice. In both cases the original `display: value` will be overridden. – Rene van der Lende Mar 09 '20 at 14:05
  • @RenevanderLende check the first and second snippet. I am trying to make the answer generic to cover all the cases and not only this particular case. In more complex cases you will need such trick and the code of OP is only a small portion so we don't know if there is more CSS involved – Temani Afif Mar 09 '20 at 14:07
  • It is a great generic rule, I do see the beauty in what you are doing here, hence no 'answer' by me. However, you got me contemplating: what when more than one attribute needs to be addressed and what about other mobile/desktop exceptions to that rule. And what about backward compatibility regarding 'custom variables'? I too love toying with those, but if you need to create a fallback for 'custom variables' you may just as well leave them out. Too off topic?? – Rene van der Lende Mar 09 '20 at 14:18
-1

Please use as below

@media all and (max-width:768px){
   .desktopOnly{
      display:none;
   }
   .mobileOnly.inlineBlock{
      display: inline-block;
   }
   .mobileOnly.flex{
      display: flex;
   }
}

@media all and (min-width:768px){
   .mobileOnly{
      display:none;
   }
   .desktopOnly.inlineBlock{
      display: inline-block;
   }
   .desktopOnly.flex{
      display: flex;
   }
}