Redupkan seluruh layar kecuali area tetap?

89

Saya ingin membuat tutorial yang akan mengarahkan pengguna tepat ke mana harus mengklik. Saya mencoba untuk menutupi seluruh layar dengan <div>yang akan redup semua elemen kecuali wilayah tertentu yang dalam tetap width, height, topdan left.

Masalahnya adalah, saya tidak dapat menemukan cara untuk "membatalkan" milik orang tua background-color(yang juga transparan).

Di potongan di bawah ini, holeadalah div yang seharusnya tidak ada background-color, termasuk milik induknya.

Bisakah ini dicapai sama sekali? Ada ide?

#bg{
   background-color:gray;
   opacity:0.6;
   width:100%;
   height:100vh;
}
#hole{
   position:fixed;
   top:100px;
   left:100px;
   width:100px;
   height:100px;
}
<div id="bg">
    <div id="hole"></div>
</div>

Berikut gambar mockup dari apa yang saya coba capai:

masukkan deskripsi gambar di sini

Koby Douek
sumber
13
Jika Anda membuat tur fitur / tutorial, Anda mungkin tertarik dengan salah satu perpustakaan js untuk melakukan ini. Mereka memiliki beberapa fitur bagus dan akan menyelamatkan Anda dari masalah menulis banyak efek css satu kali. Lihat introjs.com atau linkedin.github.io/hopscotch .
octern
2
Ini hanya saran untuk lib: heelhook.github.io/chardin.js
Thomas online

Jawaban:

126

Anda dapat melakukannya hanya dengan satu divdan memberikannya box-shadow.

EDIT: seperti yang ditunjukkan @Nick Shvelidze, Anda harus mempertimbangkan untuk menambahkanpointer-events: none

Nilai vmaxtambah box-shadowseperti yang disarankan @Prinzhorn

div {
  position: fixed;
  width: 200px;
  height: 200px;
  top: 50px;
  left: 50px;
  /* for IE */
  box-shadow: 0 0 0 1000px rgba(0,0,0,.3);
  /* for real browsers */
  box-shadow: 0 0 0 100vmax rgba(0,0,0,.3);
  pointer-events: none;
}
<div></div>

VilleKoo
sumber
29
Pastikan untuk menambahkan pointer-events: nonejika Anda ingin area di bawahnya dapat diklik.
Nick Shvelidze
4
1.000px tampaknya tidak cukup bagi saya - sepertinya akan ada terlalu banyak kasus di mana ini tidak memenuhi layar, jika tidak solusi yang sangat pintar.
ESR
1
@EdmundReed Anda dapat menyesuaikannya untuk kebutuhan Anda :)
VilleKoo
8
box-shadow: 0 0 0 100vmax rgba(0,0,0,.3);akan dijamin untuk menutupi seluruh layar
Prinzhorn
2
@VilleKoo Anda dapat menambahkannya di belakang garis 1000px dan menyimpannya sebagai mundur
Prinzhorn
19

Anda dapat membuat SVG yang diisi dengan jalur yang memiliki lubang di mana Anda membutuhkannya. Tapi saya rasa daripada Anda perlu menemukan cara untuk menangani klik, karena semuanya akan ditargetkan ke svg yang dilapisi. Saya document.getElementFromPointbisa membantu Anda di sini. mdn

philipp
sumber
Saya pikir formulir umpan balik google menggunakan svg untuk meredupkan area istirahat.
Durga
3

Ini juga dapat dilakukan dengan cara yang mirip dengan jawaban @ VilleKoo, tetapi dengan batas.

div {
    border-style: solid;
    border-color: rgba(0,0,0,.3);
    pointer-events: none;
    position: absolute;
    top: 0; bottom: 0; left: 0; right: 0;
    border-width: 40px 300px 50px 60px;
}
<div></div>

Dan
sumber
2

Anda dapat mencapai hal yang sama seperti dalam jawaban VilleKoo menggunakan outlineproperti CSS . Ini memiliki dukungan browser yang sangat baik (dan bekerja juga di IE8 +). Garis memiliki sintaks yang sama dengan garis tepi, tetapi tidak seperti garis tepi, garis tersebut tidak memakan ruang, garis tersebut digambar di atas konten.

Juga untuk IE9 + Anda dapat mengganti 99999pxdengan calc(100 * (1vh + 1vw - 1vmin)).

Kerugian dari pendekatan ini adalah yang outlinetidak terpengaruh oleh border-radius.

Demo:

div {
  position: fixed;
  width: 200px;
  height: 200px;
  top: 50px;
  left: 50px;
  /* IE8 */
  outline: 99999px solid rgba(0,0,0,.3);
  /* IE9+ */
  outline: calc(100 * (1vw + 1vh - 1vmin)) solid rgba(0,0,0,.3);
  /* for other browsers */
  outline: 100vmax solid rgba(0,0,0,.3);
  pointer-events: none;
}
<div></div>

Vadim Ovchinnikov
sumber
0

Berikut adalah kode jQuery sederhana menggunakan @VilleKoo css

var Dimmer = (function(){
  var el = $(".dimmer");
  
  return {
    showAt: function(x, y) {
      el
        .css({
          left: x,
          top: y,
        })
        .removeClass("hidden");
    },
    
    hide: function() {
      el.addClass("hidden");
    }
  }
}());


$(".btn-hide").click(function(){ Dimmer.hide(); });
$(".btn-show").click(function(){ Dimmer.showAt(50, 50); });
.dimmer {
  position: fixed;
  width: 200px;
  height: 200px;
  top: 50px;
  left: 50px;
  box-shadow: 0 0 0 1000px rgba(0,0,0,.3); /* for IE */
  box-shadow: 0 0 0 100vmax rgba(0,0,0,.3); /* for real browsers */
  pointer-events: none;
}

.hidden { display: none; }
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>

  <div>
    <input type="text">
    <select name="" id=""></select>
    <input type="checkbox">
  </div>
  <div>
    <input type="text">
    <select name="" id=""></select>
    <input type="checkbox">
  </div>
  <div>
    <input type="text">
    <select name="" id=""></select>
    <input type="checkbox">
  </div>
  <div>
    <input type="submit" disabled>
  </div>
  
  <input type="button" value="Hide" class="btn-hide">
  <input type="button" value="Show" class="btn-show">
  <div class="dimmer hidden"></div>
  <script src="https://code.jquery.com/jquery-2.2.4.js"></script>
</body>
</html>

Buksy
sumber
0
#bg {
   background-color: gray;
   opacity: 0.6;
   position: absolute;
   top: 0;
   left: 0;
   width: 100%;
   height: 100%;
   z-index: 99998;
}
#hole {
   position: fixed;
   top: 100px;
   left: 100px;
   width: 100px;
   height: 100px;
   z-index: 99999;
}
zerdnelemo.dll
sumber