4

So currently I have a UI slider that is changing data on a price-list form as the value changes, the problem I can't seem to figure out is how to grey out one or more of these boxes if a certain value hits.

I attached an image to explain what I want to achieve when 1 user is selected on the slider and what I want it to show if 2-4 users are selected on the UI slider. Any help would be greatly appreciated I really am struggling with this.

enter image description here I made in photoshop to explain better what I hope to achieve, I removed the code I tried with because it wasn't working and not sure if I was going at it the right way, any help I would be grateful for as I am really hitting my head against the wall here.

I need to grey out the following div box when the slider moves

<div class="pricing-item">
      <div class="pricing-item-inner">
        <div class="pricing-item-content">
          <div class="pricing-item-header">
            <div class="pricing-item-title">Advanced</div>
            <div
              class="pricing-item-price"
              data-price-output='{
                  "0": ["$", "13", "/m"],
                  "1": ["$", "17", "/m"],
                  "2": ["$", "21", "/m"],
                  "3": ["$", "25", "/m"],
                  "4": ["$", "42", "/m"]
                }'
            >
              <span class="pricing-item-price-currency"></span>
              <span class="pricing-item-price-amount"></span>
              <span class="pricing-item-price-after"></span>
            </div>
          </div>
          <div class="pricing-item-features">
            <ul class="pricing-item-features-list">
              <li class="is-checked">Excepteur sint occaecat</li>
              <li class="is-checked">Excepteur sint occaecat</li>
              <li class="is-checked">Excepteur sint occaecat</li>
              <li class="is-checked">Excepteur sint occaecat</li>
              <li class="is-checked">Excepteur sint occaecat</li>
            </ul>
          </div>
        </div>
        <div class="pricing-item-cta">
          <a class="button" href="#">Buy Now</a>
        </div>
      </div>
    </div>

Here is the link to codepen for the code: https://codepen.io/daniel-smit/pen/ZEQELRa

Any help really would be appreciated.

2 Answers 2

1
+100

To make it work in the way you want, you have to create an overlay <div> with position:absolute inside each pricing-item tag element along with some other styles to position it inside its pricing-item parent, give pricing-item position relative, so that it will be position reference for the overlays. also add unique class for each of the three pricing-item, I give them left, middle and right class, so that we can reference them based on the slider <range> input.

.pricing-item {
  flex-basis: 280px;
  max-width: 280px;
  box-sizing: content-box;
  padding: 12px;
  position: relative;
}

.overlay {
  position: absolute;
  left: 12px;
  top: 0;
  background-color: rgba(0, 0, 0, 0.5);
  width: calc(100% - 24px);
  height: calc(100% - 12px);
  display: none;
  z-index: 1;
}

and inside handlePricingSlider() function I add this code:

let val = +input.el.value;
document.querySelectorAll(".pricing-item.overlay").forEach((el) => {
  el.style.display = "none";
});
if (val === 0) {
  document
    .querySelectorAll(
      ".pricing-item.left .overlay, .pricing-item.right .overlay"
    )
    .forEach((el) => {
      el.style.display = "block";
    });
} else if (val === 1) {
  document.querySelectorAll(".pricing-item.right .overlay").forEach((el) => {
    el.style.display = "block";
  });
} else if (val > 1) {
  document.querySelectorAll(".pricing-item.right .overlay").forEach((el) => {
    el.style.display = "none";
  });
}

What this code do is first reset/remove the overlay <div> on all element then check for the <range> input value, if the value is 0 it will gray-out left and right columns, if its 1 it will gray-out the right column, else the layout will be removed.

Here is a snippet:

(function () {
  const pricingSliders = document.querySelectorAll(".pricing-slider");

  if (pricingSliders.length > 0) {
    for (let i = 0; i < pricingSliders.length; i++) {
      const pricingSlider = pricingSliders[i];

      // Build the input object
      const pricingInput = {
        el: pricingSlider.querySelector("input"),
      };
      pricingInput.data = JSON.parse(
        pricingInput.el.getAttribute("data-price-input")
      );
      pricingInput.currentValEl = pricingSlider.querySelector(
        ".pricing-slider-value"
      );
      pricingInput.thumbSize = parseInt(
        window
          .getComputedStyle(pricingInput.currentValEl)
          .getPropertyValue("--thumb-size"),
        10
      );

      // Build the output array
      const pricingOutputEls = pricingSlider.parentNode.querySelectorAll(
        ".pricing-item-price"
      );
      const pricingOutput = [];
      for (let i = 0; i < pricingOutputEls.length; i++) {
        const pricingOutputEl = pricingOutputEls[i];
        const pricingOutputObj = {};
        pricingOutputObj.currency = pricingOutputEl.querySelector(
          ".pricing-item-price-currency"
        );
        pricingOutputObj.amount = pricingOutputEl.querySelector(
          ".pricing-item-price-amount"
        );
        pricingOutputObj.after = pricingOutputEl.querySelector(
          ".pricing-item-price-after"
        );
        pricingOutputObj.data = JSON.parse(
          pricingOutputEl.getAttribute("data-price-output")
        );
        pricingOutput.push(pricingOutputObj);
      }

      pricingInput.el.setAttribute("min", 0);
      pricingInput.el.setAttribute(
        "max",
        Object.keys(pricingInput.data).length - 1
      );
      !pricingInput.el.getAttribute("value") &&
        pricingInput.el.setAttribute("value", 0);

      handlePricingSlider(pricingInput, pricingOutput);
      window.addEventListener("input", function () {
        handlePricingSlider(pricingInput, pricingOutput);
      });
    }
  }

  function handlePricingSlider(input, output) {
    // output the current slider value
    if (input.currentValEl)
      input.currentValEl.innerHTML = input.data[input.el.value];

    // update prices
    for (let i = 0; i < output.length; i++) {
      const outputObj = output[i];
      if (outputObj.currency)
        outputObj.currency.innerHTML = outputObj.data[input.el.value][0];
      if (outputObj.amount)
        outputObj.amount.innerHTML = outputObj.data[input.el.value][1];
      if (outputObj.after)
        outputObj.after.innerHTML = outputObj.data[input.el.value][2];
    }
    handleSliderValuePosition(input);
    let val = +input.el.value;
    document.querySelectorAll(".pricing-item .overlay").forEach((el) => {
      el.style.display = "none";
    });
    if (val === 0) {
      document
        .querySelectorAll(
          ".pricing-item.left .overlay, .pricing-item.right .overlay"
        )
        .forEach((el) => {
          el.style.display = "block";
        });
    } else if (val === 1) {
      document
        .querySelectorAll(".pricing-item.right .overlay")
        .forEach((el) => {
          el.style.display = "block";
        });
    } else if (val > 1) {
      document
        .querySelectorAll(".pricing-item.right .overlay")
        .forEach((el) => {
          el.style.display = "none";
        });
    }
  }

  function handleSliderValuePosition(input) {
    const multiplier = input.el.value / input.el.max;
    const thumbOffset = input.thumbSize * multiplier;
    const priceInputOffset =
      (input.thumbSize - input.currentValEl.clientWidth) / 2;
    input.currentValEl.style.left =
      input.el.clientWidth * multiplier - thumbOffset + priceInputOffset + "px";
  }
})();
*,
*:before,
*:after {
	box-sizing: border-box;
}

html {
	font-size: 16px;
	line-height: 24px;
	letter-spacing: -0.1px;
}

body {
	color: #607090;
	font-size: 1rem;
	margin: 0;
	padding: 48px;
	-moz-osx-font-smoothing: grayscale;
	-webkit-font-smoothing: antialiased;
}

body,
button,
input,
select,
textarea {
	font-family: "Heebo", sans-serif;
	font-weight: 400;
}

.button {
	display: flex;
	width: 100%;
	font-size: 14px;
	line-height: 22px;
	font-weight: 700;
	padding: 12px 29px;
	text-decoration: none !important;
	text-transform: uppercase;
	color: #ffffff;
	background-color: #5f48ff;
	border-width: 1px;
	border-style: solid;
	border-color: transparent;
	border-radius: 2px;
	cursor: pointer;
	justify-content: center;
	text-align: center;
	letter-spacing: inherit;
	white-space: nowrap;
	transition: background 0.15s ease;
}

input[type="range"] {
	-moz-appearance: none;
	-webkit-appearance: none;
	background: #eef1f6;
	border-radius: 3px;
	height: 6px;
	width: 100%;
	margin-top: 15px;
	margin-bottom: 15px;
	outline: none;
}

input[type="range"]::-webkit-slider-thumb {
	appearance: none;
	-webkit-appearance: none;
	background-color: #5f48ff;
	background-image: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2212%22%20height%3D%228%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M8%20.5v7L12%204zM0%204l4%203.5v-7z%22%20fill%3D%22%23FFFFFF%22%20fill-rule%3D%22nonzero%22%2F%3E%3C%2Fsvg%3E");
	background-position: center;
	background-repeat: no-repeat;
	border: 0;
	border-radius: 50%;
	cursor: pointer;
	height: 36px;
	width: 36px;
}

input[type="range"]::-moz-range-thumb {
	background-color: #5f48ff;
	background-image: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2212%22%20height%3D%228%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M8%20.5v7L12%204zM0%204l4%203.5v-7z%22%20fill%3D%22%23FFFFFF%22%20fill-rule%3D%22nonzero%22%2F%3E%3C%2Fsvg%3E");
	background-position: center;
	background-repeat: no-repeat;
	border: 0;
	border: none;
	border-radius: 50%;
	cursor: pointer;
	height: 36px;
	width: 36px;
}

input[type="range"]::-ms-thumb {
	background-color: #5f48ff;
	background-image: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2212%22%20height%3D%228%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M8%20.5v7L12%204zM0%204l4%203.5v-7z%22%20fill%3D%22%23FFFFFF%22%20fill-rule%3D%22nonzero%22%2F%3E%3C%2Fsvg%3E");
	background-position: center;
	background-repeat: no-repeat;
	border: 0;
	border-radius: 50%;
	cursor: pointer;
	height: 36px;
	width: 36px;
}

input[type="range"]::-moz-focus-outer {
	border: 0;
}

.pricing-slider {
	max-width: 280px;
	margin: 0 auto;
}

.form-slider span {
	display: block;
	font-weight: 500;
	text-align: center;
	margin-bottom: 16px;
}

.pricing-slider {
	margin-bottom: 48px;
}

.pricing-slider {
	max-width: 280px;
	margin-left: auto;
	margin-right: auto;
	position: relative;
}

.pricing-slider input {
	width: 100%;
}

.pricing-slider .pricing-slider-value {
	position: absolute;
	font-size: 14px;
	line-height: 22px;
	font-weight: 500;
	color: #909cb5;
	margin-top: 8px;
	--thumb-size: 36px;
}

.pricing-items {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	margin-right: -12px;
	margin-left: -12px;
	margin-top: -12px;
}

.pricing-item {
	flex-basis: 280px;
	max-width: 280px;
	box-sizing: content-box;
	padding: 12px;
	position: relative;
}

.overlay {
	position: absolute;
	left: 12px;
	top: 0;
	background-color: rgba(0, 0, 0, 0.5);
	width: calc(100% - 24px);
	height: calc(100% - 12px);
	display: none;
	z-index: 1;
}

.pricing-item-inner {
	display: flex;
	flex-wrap: wrap;
	flex-direction: column;
	height: 100%;
	padding: 24px;
	box-shadow: 0 8px 16px rgba(46, 52, 88, 0.16);
}

.pricing-item-title {
	font-weight: 500;
}

.pricing-item-price {
	display: inline-flex;
	align-items: baseline;
	font-size: 20px;
}

.pricing-item-price-amount {
	font-size: 36px;
	line-height: 48px;
	font-weight: 500;
	color: #191e2a;
}

.pricing-item-features-list {
	list-style: none;
	padding: 0;
}

.pricing-item-features-list li {
	margin-bottom: 0;
	padding: 14px 0;
	position: relative;
	display: flex;
	align-items: center;
}

.pricing-item-features-list li::before {
	content: "";
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	display: block;
	height: 1px;
	background: #e9ecf8;
}

.pricing-item-features-list li::after {
	content: "";
	display: block;
	width: 24px;
	height: 24px;
	margin-right: 12px;
	background-image: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M5%2011h14v2H5z%22%20fill%3D%22%239298B8%22%20fill-rule%3D%22nonzero%22%2F%3E%3C%2Fsvg%3E");
	background-repeat: no-repeat;
	-webkit-box-ordinal-group: 0;
	order: -1;
}

.pricing-item-features-list li.is-checked::after {
	background-image: url("data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cg%20fill-rule%3D%22nonzero%22%20fill%3D%22none%22%3E%3Ccircle%20fill%3D%22%2300C2A9%22%20cx%3D%2212%22%20cy%3D%2212%22%20r%3D%2212%22%2F%3E%3Cpath%20fill%3D%22%23fff%22%20d%3D%22M10.5%2012.267l-2.5-1.6-1%201.066L10.5%2016%2017%209.067%2016%208z%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
}
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>Pricing Switcher</title>
        <link href="https://fonts.googleapis.com/css?family=Heebo:400,500&display=swap" rel="stylesheet" />
        <link rel="stylesheet" href="style.css" />
        <style></style>
    </head>
    <body>
        <div class="pricing">
            <div class="pricing-slider">
                <label class="form-slider">
                    <span>How many users do you have?</span>
                    <input
                        type="range"
                        value="1"
                        data-price-input='{
                "0": "1",
                "1": "2-4",
                "2": "5-9",
                "3": "10-24",
                "4": "25+"                       
              }'
                    />
                </label>
                <div class="pricing-slider-value"></div>
            </div>

            <div class="pricing-items">
                <div class="pricing-item left">
                    <div class="overlay"></div>
                    <div class="pricing-item-inner">
                        <div class="pricing-item-content">
                            <div class="pricing-item-header">
                                <div class="pricing-item-title">Basic</div>
                                <div
                                    class="pricing-item-price"
                                    data-price-output='{
                    "0": ["", "Free", ""],
                    "1": ["$", "13", "/m"],
                    "2": ["$", "17", "/m"],
                    "3": ["$", "21", "/m"],
                    "4": ["$", "25", "/m"]
                  }'
                                >
                                    <span class="pricing-item-price-currency"></span>
                                    <span class="pricing-item-price-amount"></span>
                                    <span class="pricing-item-price-after"></span>
                                </div>
                            </div>
                            <div class="pricing-item-features">
                                <ul class="pricing-item-features-list">
                                    <li class="is-checked">
                                        <div
                                            class="pricing-item-price"
                                            data-price-output='{
                    "0": ["Demo text 1"],
                    "1": ["Demo text 2"],
                    "2": ["Demo text 3"],
                    "3": ["Demo text 4"],
                    "4": ["Demo text 5"]
                  }'
                                        >
                                            <span class="pricing-item-price-currency"></span>
                                        </div>
                                    </li>

                                    <li class="is-checked">Excepteur sint occaecat</li>
                                    <li class="is-checked">Excepteur sint occaecat</li>
                                    <li>Excepteur sint occaecat</li>
                                    <li>Excepteur sint occaecat</li>
                                </ul>
                            </div>
                        </div>
                        <div class="pricing-item-cta">
                            <a class="button" href="#">Buy Now</a>
                        </div>
                    </div>
                </div>

                <div class="pricing-item middle">
                    <div class="overlay"></div>
                    <div class="pricing-item-inner">
                        <div class="pricing-item-content">
                            <div class="pricing-item-header">
                                <div class="pricing-item-title">Advanced</div>
                                <div
                                    class="pricing-item-price"
                                    data-price-output='{
                      "0": ["$", "13", "/m"],
                      "1": ["$", "17", "/m"],
                      "2": ["$", "21", "/m"],
                      "3": ["$", "25", "/m"],
                      "4": ["$", "42", "/m"]
                    }'
                                >
                                    <span class="pricing-item-price-currency"></span>
                                    <span class="pricing-item-price-amount"></span>
                                    <span class="pricing-item-price-after"></span>
                                </div>
                            </div>
                            <div class="pricing-item-features">
                                <ul class="pricing-item-features-list">
                                    <li class="is-checked">Excepteur sint occaecat</li>
                                    <li class="is-checked">Excepteur sint occaecat</li>
                                    <li class="is-checked">Excepteur sint occaecat</li>
                                    <li class="is-checked">Excepteur sint occaecat</li>
                                    <li class="is-checked">Excepteur sint occaecat</li>
                                </ul>
                            </div>
                        </div>
                        <div class="pricing-item-cta">
                            <a class="button" href="#">Buy Now</a>
                        </div>
                    </div>
                </div>

                <div class="pricing-item right">
                    <div class="overlay"></div>
                    <div class="pricing-item-inner">
                        <div class="pricing-item-content">
                            <div class="pricing-item-header">
                                <div class="pricing-item-title">Enterprise</div>
                                <div
                                    class="pricing-item-price"
                                    data-price-output='{
                      "0": ["$", "22", "/m"],
                      "1": ["$", "33", "/m"],
                      "2": ["$", "42", "/m"],
                      "3": ["$", "88", "/m"],
                      "4": ["$", "105", "/m"]
                    }'
                                >
                                    <span class="pricing-item-price-currency"></span>
                                    <span class="pricing-item-price-amount"></span>
                                    <span class="pricing-item-price-after"></span>
                                </div>
                            </div>
                            <div class="pricing-item-features">
                                <ul class="pricing-item-features-list">
                                    <li class="is-checked">Excepteur sint occaecat</li>
                                    <li class="is-checked">Excepteur sint occaecat</li>
                                    <li class="is-checked">Excepteur sint occaecat</li>
                                    <li class="is-checked">Excepteur sint occaecat</li>
                                    <li class="is-checked">Excepteur sint occaecat</li>
                                </ul>
                            </div>
                        </div>
                        <div class="pricing-item-cta">
                            <a class="button" href="#">Buy Now</a>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <script></script>
    </body>
</html>

Sign up to request clarification or add additional context in comments.

Comments

0

Here is the updated code: https://codepen.io/tahabayi/pen/ExPaOKW

HTML (mask div should be added under each inner div, and mask div can be enhanced according to needs)

    <div class="pricing-item">
        <div class="pricing-item-inner">
            <div class="pricing-item-inner pricing-item-inner-mask"></div>
                .
                .
        </div>
    </div>

CSS

    .pricing-item-inner {
        .
        .
        position: relative;
    }
    .mask {
        display: block !important;
    }
    .pricing-item-inner-mask {
        background: gray;
        opacity: 80%;
        position: absolute;
        width: 100%;
        height: 100%;
        left: 0;
        top: 0;
        z-index: 1;
        display: none;
    }

JS

    .
    .
    pricingOutputObj.after = pricingOutputEl.querySelector(
        ".pricing-item-price-after"
    );
    pricingOutputObj.mask = pricingOutputEl.parentNode.parentNode.parentNode.querySelector(
        ".pricing-item-inner-mask"
    );
    .
    .
    if (outputObj.after)
        outputObj.after.innerHTML = outputObj.data[input.el.value][2];
    if (outputObj.mask) {
        outputObj.mask.classList.remove("mask");
        if ((input.el.value == '0' && (i == 0 || i ==3)) || (input.el.value == '1' && i == 3)) {
          outputObj.mask.classList.add("mask");
        }
    }
    .
    .

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.