12

How can I make a greyed out overlay on a page, but have one element in that page not greyed out?

There are many questions like this asked but none of them work:

From the example below I want everything greyed out except for <input class="edit-title" value="Site Title">. Right now my code greys out most of the page, I can grey out the whole page if I change

.overlay {
  z-index: -1;
}

to

.overlay {
  z-index: 0;
}

Is there a way to grey out everything except <input class="edit-title" value="Site Title">?

html {
  box-sizing: border-box;
}

.overlay {
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  position: absolute;
  background: rgba(0, 0, 0, .4);
  z-index: -1;
}

edit-title {
  z-index: 100;
}
*,
*:before,
*:after {
  box-sizing: inherit;
}

body,
input,
optgroup,
select,
textarea {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
}

body {
  font-size: 13px;
  line-height: 1.4;
  color: #555;
  margin: 0;
  padding: 0;
  background: white;
  overflow-x: hidden;
}

.button {
  font-weight: bold;
  color: #fff;
  border: 1px solid #44aa76;
  border-width: 0 0 3px 0;
  background-color: #66cc98;
  padding: 5px;
  border-radius: 6px;
  text-align: center;
}

.button:focus,
.button:hover,
.active {
  cursor: pointer;
  background-color: #44aa76;
  color: #fff;
  outline: none;
}

header {
  width: 100%;
  border-bottom: 1px solid #eee;
  display: flex;
  justify-content: center;
  padding: 30px 0 10px;
  margin-bottom: 10px;
}

input {
  font-size: 13px;
  border: 1px solid #eee;
  border-radius: 4px;
  padding: 8px;
}

input:focus {
  outline: none;
  border-color: #ddd;
}

[type="search"] {
  -webkit-appearance: textfield;
}

[type="search"]::-webkit-search-cancel-button,
[type="search"]::-webkit-search-decoration {
  -webkit-appearance: none;
}

.search {
  display: flex;
  align-items: center;
  border-bottom: 1px solid #eee;
  padding-bottom: 10px;
}

.search input[type="search"] {
  width: 100%;
}

label {
  font-size: 13px;
  margin-right: 5px;
}

.save-button {
  width: 30px;
  height: 30px;
  line-height: 27px;
  padding: 0;
  margin: 0 10px;
}

h1 {
  margin: 0;
  padding: 0;
  line-height: 1;
  font-size: 22px;
  padding: 4px 0;
}

.container {
  position: relative;
  padding: 0 15px;
  width: 360px;
  max-width: 100%;
  margin: 0;
}

.reading-list {
  margin-bottom: 15px;
}

.reading-item {
  border-radius: 3px;
  padding: 0;
  margin: 10px 0 0 0;
  background-color: #f7f7f7;
  position: relative;
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15), 0 2px 3px rgba(0, 0, 0, 0.05);
  transition: all 0.5s ease 0s;
}

.reading-item .item-link {
  text-decoration: none;
  display: block;
  width: 100%;
  color: #555;
  padding: 10px 50px 10px 56px;
  min-height: 56px;
}

.reading-item .item-link:focus,
.reading-item .item-link:hover {
  color: #66cc98;
  background-color: #fff;
}

.reading-item .item-link span {
  display: block;
}

.reading-item .item-link span.title {
  font-weight: bold;
}

.reading-item .favicon {
  position: absolute;
  top: 10px;
  left: 10px;
  width: 36px;
  height: 36px;
  border-radius: 4px;
  border: 1px solid #ccc;
  padding: 1px;
}

.reading-item .item-link:hover .favicon {
  border-color: #66cc98;
}

.reading-item .delete-button {
  position: absolute;
  top: 5px;
  right: 5px;
  border-radius: 100%;
  padding: 0;
  width: 20px;
  height: 20px;
  border: 0;
  background-color: transparent;
  color: #ccc;
  transform: rotateZ(0) scale(1);
  transition: transform 0.3s ease, box-shadow 0.5s ease;
}

.reading-item .edit-button,
.reading-item .save-button {
  position: absolute;
  bottom: 10px;
  right: 10px;
  padding: 0;
  width: 10px;
  height: 10px;
  border: 0;
  background-color: transparent;
  color: #ccc;
  border-radius: 0;
  margin: 0;
}

.reading-item .delete-button:hover {
  background-color: #ccc;
  color: #fff;
  transform: rotateZ(90deg) scale(2);
  box-shadow: 1px 0 1px rgba(0, 0, 0, 0.15);
}
<body class="popup-page">
  <div class="container">
    <header>
      <h1 data-localize="appName">Reading List</h1>
      <button class="button save-button" id="savepage">+</button>
    </header>
    <div class="search">
      <label for="my-search" data-localize="search">Search</label>
      <input type="search" id="my-search" name="search" autocomplete="off">
    </div>

    <div class="reading-list" id="reading-list">
      <div class="reading-item read">
        <a value="www.example.com" class="button delete-button">×</a>
        <a class="item-link" href="www.example.com" alt="Reading List">
          <input class="edit-title" value="Site Title">
          <span class="host">example.com</span>
        </a>
        <img src="/icons/save.svg" class="button save-button"></div>
    </div>

  </div>
  <div class="overlay" id="overlay"></div>
</body>

https://jsfiddle.net/qyca9489/

Zub
  • 808
  • 3
  • 12
  • 23
Whitecat
  • 3,882
  • 7
  • 48
  • 78

2 Answers2

9

Can do it using css box-shadow.

.box{display:inline-block; width:100px; height:100px; margin-top:50px; text-align:center; padding-top:2em}
.box.selected{
    box-shadow: 0 0 0 99999px rgba(0, 0, 0, .5);
}
<div class="box">Box 1</div>
<div class="box">Box 2</div>
<div class="box selected">Box 3</div>
<div class="box">Box 4</div>

Alternate solution using 4 overlay elements

Overlays are positioned based on highlighted element position and dimensions.

The top and bottom overlays are 100% width. The top one just needs it's height set to value of top offset of highlighted element. Bottom one gets it's top set to bottom of the element.

Right and left are same height as highlighted element and reach to each edge of page to fill holes between the top and bottom overlays

var $el = $('.box.selected'),
  $oLay = $('.overlay'),
  elPos = $el.offset(),// coordinates of element within document
  elH = $el.height(),
  elW = $el.width();

$oLay.filter('.top').height(elPos.top);

$oLay.filter('.left').css({
  top: elPos.top,
  height: elH,
  width: elPos.left
});

$oLay.filter('.right').css({
  top: elPos.top,
  height: elH,
  left: elPos.left + elW
});

$oLay.filter('.bottom').css({
  top: elPos.top + elH
});
.box {
  display: inline-block;
  width: 100px;
  height: 100px;
  margin-top: 50px;
  text-align: center;
  padding-top: 2em
}

.overlay {
  position: absolute;
  background: rgba(0, 0, 0, .5);
  z-index: 100
}

.overlay.top {
  top: 0;
  left: 0;
  width: 100%
}

.overlay.left {
  left: 0
}

.overlay.right {
  right: 0
}

.overlay.bottom {
  width: 100%;
  left: 0;
  bottom: 0
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box">Box 1</div>
<div class="box">Box 2</div>
<div class="box selected">Box 3</div>
<div class="box">Box 4</div>


<div class="overlay top"></div>
<div class="overlay left"></div>
<div class="overlay right"></div>
<div class="overlay bottom"></div>
charlietfl
  • 170,828
  • 13
  • 121
  • 150
  • Does this work with nested boxes? For example can you put 3 boxes inside box 3, and grey out everything except for one of the nested boxes? – Whitecat Dec 12 '17 at 18:12
  • did you try it? My demo is pretty simple to enhance – charlietfl Dec 12 '17 at 18:14
  • To be honest I've never done this in production page. Just a trick I learned. In the past I always created 4 overlays and positioned them using script based on element position and dimensions – charlietfl Dec 12 '17 at 18:15
  • 1
    Added another 4 overlay approach – charlietfl Dec 12 '17 at 18:47
  • Thank you for the help! I ended up only needing to add `position: relative` to the html element to make z-index work, the way I was doing it. – Whitecat Dec 13 '17 at 18:29
  • Interesting solution with the box-shadow! Had the issue, that the shadow spans the whole window and the solution was to assign overflow: hidden to the element where the shadow should appear / span only. – Billy G Oct 20 '22 at 14:50
1

You could put a second overlay inside <a class="item-link" href="www.example.com" alt="Reading List">. So:

<a class="item-link" href="www.example.com">
  <div class="overlay"></div>
  …
</a>

And in the CSS:

.item-link {
  position: relative
}
Alexander
  • 638
  • 3
  • 11