css 悬停/选定变体上的色板边框

blmhpbnm  于 2023-05-30  发布在  其他
关注(0)|答案(1)|浏览(314)

我试图创建一个效果,我的颜色样本,如果你悬停在一个样本或选择一个黑色的固体边界出现在周围的样本与一个小的空白空白之间的空白空白和新的边界。
图片:



我尝试放大色板的大小,然后在白色边框周围添加一个黑色边框,并插入原始色板以创建间隙的错觉,但我没有正确实现这一点(请参阅以下代码),因为在选定的变体上发生的所有事情都是快速过渡,然后没有边框。
选择粉红色的图像:


.color-swatches {
  display: flex;
}

.color-swatch {
  display: inline-block;
  width: 30px; /* Adjust the width of each color swatch */
  height: 30px; /* Adjust the height of each color swatch */
  margin-right: 15px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}

.color-swatch::before {
  content: "";
  position: absolute;
  top: -3px;
  left: -3px;
  right: -3px;
  bottom: -3px;
  border: 3px solid white;
  border-radius: 5px;
  box-sizing: border-box;
  z-index: -1;
}

.color-swatch:hover::before,
.color-swatch input[type="radio"]:checked + span::before {
  top: -5px;
  left: -5px;
  right: -5px;
  bottom: -5px;
  border: 5px solid white;
}

.color-swatch input[type="radio"] {
  display: none;
}

.color-swatch span {
  display: block;
  width: 100%;
  height: 100%;
  border: 1px solid #4b4b4b;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
  transition: transform 0.3s ease;
}

.color-swatch input[type="radio"]:checked + span {
  border-color: #000;
  transform: scale(1.2); /* Scale up the swatch when selected */
}

.color-swatch input[type="radio"]:checked + span::after {
  content: "";
  position: absolute;
  inset: -2px;
  border: 2px solid #000;
  border-radius: 3px;
  transform: scale(1.2); /* Scale up the gap illusion border when selected */
  transition: transform 0.3s ease;
}

.color-swatch input[type="radio"]:checked + span:hover::after {
  transform: scale(1.3); /* Further scale up the gap illusion border on hover when selected */
}

以下是我用于变体色板的Liquid/HTML代码:

<legend class="form__label" id="option-{{ option.name | handle }}">{{ option.name }}: <span id="selected-{{ option.name | handle }}">{{ option.selected_value }}</span></legend>
     <div class="color-swatches">
           {%- for value in option.values -%}
               {%- assign variant = product.variants | where: option.name, value | first -%}
               {%- assign swatchColor = '' -%}
               {%- case value -%}
                   {%- when 'Pink' -%}
                       {%- assign swatchColor = '#E3BAB3' -%}
                   {%- when 'Lilac' -%}
                       {%- assign swatchColor = '#CBB9E0' -%}
                   {%- when 'Navy' -%}
                       {%- assign swatchColor = '#415873' -%}
                   {%- when 'Red' -%}
                       {%- assign swatchColor = '#D63238' -%}
                   {%- when 'Tan' -%}
                       {%- assign swatchColor = '#E1BC9F' -%}
                   {%- else -%}
                       {%- assign swatchColor = '' -%}
               {%- endcase -%}
               <label for="{{ section.id }}-{{ option.position }}-{{ forloop.index0 }}" class="color-swatch" style="background-color: {{ swatchColor }};">
                   <input type="radio" id="{{ section.id }}-{{ option.position }}-{{ forloop.index0 }}"
                       name="{{ option.name }}"
                       value="{{ value | escape }}"
                       form="{{ product_form_id }}"
                       {% if option.selected_value == value %}checked{% endif %}
                       onchange="updateSelectedValue('{{ option.name | handle }}', '{{ value | escape }}')"
                   >
                   <span></span>
               </label>
           {%- endfor -%}
       </div>
pepwfjgg

pepwfjgg1#

不幸的是,您的问题不包括minimally reproducible example。所以我只会触及border的事情,因为我认为这是你的主要焦点,我不太确定你想说的transition效应。如果我理解正确的话,您希望它看起来像是在色样和边框之间有一个透明的间隙。

**更新:**我现在还实现了一个select/unselect函数(参见答案末尾的两个片段)。但是,这是使用JavaScript实现的。只有几行。还有一个基于CSS的解决方案,而不是一个CSS黑客。关于herehere的更多信息。

我将向你们展示三种方法,但其中只有一种会产生真实的的差距,另外两种会伪造差距。如果您使用图像、图案或渐变作为背景,这一点尤其重要。

使用outline属性

这可能是最快和最简单的方法。只需为element:hover分配一个常规的border和一个outline边框,其中常规边框必须是背景的颜色。所以这种方法是假的,而不是单一颜色的背景是次优的。另一件需要提及的事情。处于正常状态(无悬停)的元素需要一个透明边框,其宽度与悬停状态完全相同。否则会有大小的变化,看起来很丑。

element {
    width: 60px;
    height: 60px;
    border: 3px solid transparent;
}

element:hover {
    border:  3px solid white;  /* matches background color */
    outline: 4px solid black;  /* any color */
}

参考:https://developer.mozilla.org/docs/Web/CSS/outline

使用::after伪元素

有一件事马上,这种方法也只假一切。那么它是如何做到的呢?首先,实际元素必须位于relative,因为::after伪元素将被设置为absolute。出于与上一个示例相同的原因,这里也需要透明边框。接下来,像前面一样,为element:hover分配一个常规的border,其中常规边界必须是背景的颜色。最后,:hover状态的::after伪元素。如前所述,必须将其设置为position:absolutebackground-color用作border-color,我们通过使用具有负值的toprightbottomleft属性来获得所需的border-width。再次,这里应该说,除了单一颜色作为背景颜色之外的任何颜色都是次优的。

element {
    position: relative;
    width: 60px;
    height: 60px;
    border: 3px solid transparent;
}

element:hover {
    border: 3px solid white;  /* matches background color */
}

element:hover::after {
    content: '';
    position: absolute;
    top: -7px;
    left: -7px;
    right: -7px;
    bottom: -7px;
    background: black;  /* any color */
    z-index: -1;
}

参考:https://developer.mozilla.org//docs/Web/CSS/::after

使用background-clip属性

最好的总是在最后,这可能就是你需要的,没有虚假,但真实的的差距创造。如标题所示,此方法使用设置为content-boxbackground-clip属性。最大的好处可能是背景可以根据您的意愿进行设计。色彩渐变、图案或图像,一切皆有可能。这里的其他内容实际上是不言自明的,因为所有内容都已经在前面的两个方法中描述过了。

element {
    width: 66px;
    height: 66px;
}

element:hover {
    width: 58px;
    height: 58px;
    padding: 3px;
    margin: -3px;
    border: 4px solid black;  /* any color */
    background-clip: content-box;
}

参考:https://developer.mozilla.org/docs/Web/CSS/background-clip

工作示例

我创建了两个代码片段,以在一个工作示例中显示我刚才讨论的内容。在第一个中,使用纯色背景。这里所有的方法都能完美地工作,而在第二个代码片段中使用了一个背景模式。现在,差异是显而易见的。

片段1 -纯色背景:

let swatches = document.querySelectorAll('.swatch');

let selected = (e) => {
   let swatch = e.target;
   swatch.classList.toggle('selected');
}

swatches.forEach((item) => {
    item.addEventListener('click', selected);
});
/* General Styling */

.color-1 { background: pink; }
.color-2 { background: thistle; }
.color-3 { background: steelblue; }
.color-4 { background: crimson; }
.color-5 { background: burlywood; }

.container {
    display: flex;
    width: 100%;
    height: fit-content;
    column-gap: 20px;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
}

.container h2 {
    width: 100%;
    text-align: center;
    letter-spacing: 2px;
    font-family: monospace;
    font-size: 18px;
    color: #555;
}

.container .swatch {
    width: 60px;
    height: 60px;
    border-radius: 10px;
    cursor: pointer;
}

/* Swatch Styling */

/* using outline property */

#outline .swatch {
    border: 3px solid transparent;
}

#outline .swatch:hover {
    border: 3px solid white; 
    outline: 4px solid black;
}

#outline .swatch.selected {
    border: 3px solid white;
    outline: 4px solid orange;
}

/* using ::after pseudo element */

#pseudo .swatch {
    position: relative;
    border-radius: 10px;
    border: 3px solid transparent;
}

#pseudo .swatch:hover {
    border: 3px solid white;
}

#pseudo .swatch:hover::after {
    content: '';
    position: absolute;
    top: -7px;
    left: -7px;
    right: -7px;
    bottom: -7px;
    background: black;
    border-radius: 14px;
    z-index: -1;
}

#pseudo .swatch.selected {
    border: 3px solid white;
}

#pseudo .swatch.selected::after {
    content: '';
    position: absolute;
    top: -7px;
    left: -7px;
    right: -7px;
    bottom: -7px;
    background: orange;
    border-radius: 14px;
    z-index: -1;
}

/* using background-clip property */

#clip .swatch {
    width: 66px;
    height: 66px;
    border-radius: 10px;
}

#clip .swatch:hover {
    width: 58px;
    height: 58px;
    padding: 3px;
    margin: -3px;
    border-radius: 14px;
    border: 4px solid black;
    background-clip: content-box;
}

#clip .swatch.selected {
    width: 58px;
    height: 58px;
    padding: 3px;
    margin: -3px;
    border-radius: 14px;
    border: 4px solid orange;
    background-clip: content-box;
}
<div id="outline" class="container">
    <h2>Outline Method</h2>
    <div class="swatch color-1"></div>
    <div class="swatch color-2"></div>
    <div class="swatch color-3"></div>
    <div class="swatch color-4"></div>
    <div class="swatch color-5"></div>
</div>

<div id="pseudo" class="container">
    <h2>Pseudo Element</h2>
    <div class="swatch color-1"></div>
    <div class="swatch color-2"></div>
    <div class="swatch color-3"></div>
    <div class="swatch color-4"></div>
    <div class="swatch color-5"></div>
</div>

<div id="clip" class="container">
    <h2>Background Clip</h2>
    <div class="swatch color-1"></div>
    <div class="swatch color-2"></div>
    <div class="swatch color-3"></div>
    <div class="swatch color-4"></div>
    <div class="swatch color-5"></div>
</div>

片段2 -背景图案:

let swatches = document.querySelectorAll('.swatch');

let selected = (e) => {
   let swatch = e.target;
   swatch.classList.toggle('selected');
}

swatches.forEach((item) => {
    item.addEventListener('click', selected);
});
/* General Styling */

body {
   background: url('https://i.imgur.com/8uEAmBx.jpg') repeat;
}

.color-1 { background: pink; }
.color-2 { background: thistle; }
.color-3 { background: steelblue; }
.color-4 { background: crimson; }
.color-5 { background: burlywood; }

.container {
    display: flex;
    width: 100%;
    height: fit-content;
    column-gap: 20px;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
}

.container h2 {
    width: 100%;
    text-align: center;
    letter-spacing: 2px;
    font-family: monospace;
    font-size: 18px;
    color: #555;
}

.container .swatch {
    width: 60px;
    height: 60px;
    border-radius: 10px;
    cursor: pointer;
}

/* Swatch Styling */

/* using outline property */

#outline .swatch {
    border: 3px solid transparent;
}

#outline .swatch:hover {
    border: 3px solid white; 
    outline: 4px solid black;
}

#outline .swatch.selected {
    border: 3px solid white;
    outline: 4px solid orange;
}

/* using ::after pseudo element */

#pseudo .swatch {
    position: relative;
    border-radius: 10px;
    border: 3px solid transparent;
}

#pseudo .swatch:hover {
    border: 3px solid white;
}

#pseudo .swatch:hover::after {
    content: '';
    position: absolute;
    top: -7px;
    left: -7px;
    right: -7px;
    bottom: -7px;
    background: black;
    border-radius: 14px;
    z-index: -1;
}

#pseudo .swatch.selected {
    border: 3px solid white;
}

#pseudo .swatch.selected::after {
    content: '';
    position: absolute;
    top: -7px;
    left: -7px;
    right: -7px;
    bottom: -7px;
    background: orange;
    border-radius: 14px;
    z-index: -1;
}

/* using background-clip property */

#clip .swatch {
    width: 66px;
    height: 66px;
    border-radius: 10px;
}

#clip .swatch:hover {
    width: 58px;
    height: 58px;
    padding: 3px;
    margin: -3px;
    border-radius: 14px;
    border: 4px solid black;
    background-clip: content-box;
}

#clip .swatch.selected {
    width: 58px;
    height: 58px;
    padding: 3px;
    margin: -3px;
    border-radius: 14px;
    border: 4px solid orange;
    background-clip: content-box;
}
<div id="outline" class="container">
    <h2>Outline Method</h2>
    <div class="swatch color-1"></div>
    <div class="swatch color-2"></div>
    <div class="swatch color-3"></div>
    <div class="swatch color-4"></div>
    <div class="swatch color-5"></div>
</div>

<div id="pseudo" class="container">
    <h2>Pseudo Element</h2>
    <div class="swatch color-1"></div>
    <div class="swatch color-2"></div>
    <div class="swatch color-3"></div>
    <div class="swatch color-4"></div>
    <div class="swatch color-5"></div>
</div>

<div id="clip" class="container">
    <h2>Background Clip</h2>
    <div class="swatch color-1"></div>
    <div class="swatch color-2"></div>
    <div class="swatch color-3"></div>
    <div class="swatch color-4"></div>
    <div class="swatch color-5"></div>
</div>

相关问题