Whitecat
Whitecat

Reputation: 4020

How can I grey out page except for one element?

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/

Upvotes: 13

Views: 10041

Answers (2)

charlietfl
charlietfl

Reputation: 171669

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>

Upvotes: 12

Alexander
Alexander

Reputation: 658

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
}

Upvotes: 1

Related Questions