cssprintingsassselectorresponsive

SCSS how to write CSS styling applies for both media print and a specific case


I have a special case where my styling needs to be applied to both Print media and when the <body> has a special class to detect, let's just call this class .is-pdf-mode.

In my SCSS, I tried to use @content to avoid repeating CSS but somehow, the resulted CSS doesn't generate a correct selector for the <body> case, I cannot use & selector inside this mixin. So far this is my attempt.

SCSS:

@mixin query-print {
  @media print {
    @content;
  }

  .body.is-pdf-mode {
    @content;
  }
}

.box {
  width: 200px;
  height: 200px;
  background: lightsalmon;
  margin: 15px;

  @include query-print {
    background: green;
  }
}

@media print {
// Default styling only apply for print
html,
body,
page[size="A4"] {
    padding:0px;
    margin:0px;
    width: 210mm;
    height: 297mm;
}

body {
  -webkit-print-color-adjust: exact !important;
  zoom: 100%;
}

}

HTML:

<div class="body">
  <div class="box">
    hello
  </div>
</div>

<div class="body is-pdf-mode">
  <div class="box">
    hello
  </div>
</div>

I understand that by writing .body.is-pdf-mode inside that mixin, that would mean .box .body.is-pdf-mode, it should be .body.is-pdf-mode .box instead. So, my question is what's the correct way to write CSS in this situation ?

Codepen attempt: https://codepen.io/DieByMacro/pen/xoLNpE

Update 1: rewrite my CSS inside query-print mixin:

If I write like this:

.box {
  width: 200px;
  height: 200px;
  background: lightsalmon;
  margin: 15px;
}

@include query-print {
.box {
  background: green;
}
}

Obviously this will work, but in my real project we've adopted using @include mixin inside selector. By applying this strategy, it means re-writing a lot of selector, so I think this would be my last resort when there's no other choices.

Thanks,


Solution

  • You can use @at-root and the parent selector &:

    @mixin query-print {
      @media print {
        @content;
      }
    
      @at-root.body.is-pdf-mode #{&} {
        @content;
      }
    }
    

    With your example, it will return:

    @media print {
      .box {
        background: green;
      }
    }
    
    .body.is-pdf-mode .box {
      background: green;
    }