Is there a way to create a button (or div) with a border that has a gradient and has rounded corners?

前提是你 提交于 2020-01-21 10:59:04

问题


This is what it should look like:

Attempts so far:

  1. Using a gradient background plus an inner element to cover it and leave just an outer "border". The background is obviously not transparent.

body {
  background: #242424;
  height: 100%;
  width: 100%;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: sans-serif;
  color: #FFFFFF;
}

div {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-content: center;
  align-items: center;
  width: 100%;
  height: 100vh;
}

h1 {
  margin: 2em;
  text-align: center;
}

a {
  cursor: pointer;
  transition: ease-in-out,.2s,color;
}
a:hover {
  color: #DDD;
}

.nested {
  display: block;
  max-width: 20em;
  padding: 2px;
  overflow: hidden;
  border-radius: 2em;
  background: linear-gradient(to right, #00ff00 0%, #00e5ff 100%);
}
.nested span {
  display: inline-block;
  padding: 1em;
  text-align: center;
  background: #242424;
  border-radius: 2rem;
}
.nested span p {
  padding: 0 2em;
  margin: 0;
}

.pseudo {
  display: block;
  margin-top: 20px;
  position: relative;
  border-radius: 2em;
  padding: 1em 2em;
  background: #242424;
}
.pseudo:after {
  position: absolute;
  z-index: -1;
  top: -2px;
  bottom: -2px;
  right: -2px;
  left: -2px;
  background: linear-gradient(to right, #00ff00 0%, #00e5ff 100%);
  border-radius: 2em;
  content: '';
}
<div>
    <h1>Gradient + Border Radius</h1>
    <a class="nested"><span><p>ANOTHER ONE</p></span></a>
    <a class="pseudo">AND ANOTHER ONE</a>
</div>
  1. Using border-image. The corners are not rounded.

body {
  background: url(http://subtlepatterns2015.subtlepatterns.netdna-cdn.com/patterns/ignasi_pattern_s.png);
  height: 100%;
  width: 100%;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: sans-serif;
}

a {
  padding: 20px 40px;
  border-image: linear-gradient(to bottom right, #00aeef 0%, #7cc578 100%);
  border-image-slice: 1;
  border-radius: 10px;
}

div {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-content: center;
  align-items: center;
  width: 100%;
  height: 100vh;
}

h1 {
  margin: 2em;
  text-align: center;
}

a {
  text-decoration: none;
  font-weight: bold;
  color: black;
  cursor: pointer;
  transition: ease-in-out,.2s,color;
}
a:hover {
  color: #DDD;
}
<div>
    <h1>Gradient + [non working] Border Radius</h1>
    <a href="#">CLICK ME	</a>
</div>

回答1:


No, you can't use border-image on an element with border-radius because as per specs, only the background of the element is clipped based on border radius and not the border-image. So the image would always be a rectangle (or square).

If the need is for a transparent center portion (or a transparent content area) then the best bet is to use SVG. SVG's stroke can take even a gradient as value and so it can produce a rounded shape whose border is a gradient and center portion is transparent.

The path used for creating the shape is simple and you can read more about path commands here.

.border-with-grad {
  position: relative;
  height: 100px;
  width: 250px;
  color: white;
  line-height: 100px;
  text-align: center;
  letter-spacing: 1.5px;
}
.border-with-grad svg {
  position: absolute;
  top: 0px;
  left: 0px;
  height: 100%;
  width: 100%;
}
.border-with-grad path {
  fill: transparent;
  stroke: url(#border-gradient);
  stroke-width: 4;
}

/* Just for demo */

body {
  background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
  min-height: 100vh;
  font-family: sans-serif;  
}
<div class='border-with-grad'>
  <svg viewBox='0 0 250 100'>
    <defs>
      <linearGradient id='border-gradient' gradientUnits='objectBoundingBox' gradientTransform='rotate(5 0.5 0.5)'>
        <stop offset='0%' stop-color='rgb(248,244,135)' />
        <stop offset='25%' stop-color='rgb(248,244,135)' />
        <stop offset='75%' stop-color='rgb(53,176,182)' />
        <stop offset='100%' stop-color='rgb(53,176,182)' />
      </linearGradient>
    </defs>
    <path d='M50,95 a45,45 0 0,1 0,-90 h150 a45,45 0 1,1 0,90 h-150' />
  </svg>
  CLICK HERE
</div>

With CSS, we can use mask-image to make the center portion as transparent but its browser support is very poor. At present only webkit powered browsers support this property. Another way would be to make use of clip-path but that is no-go if you need to support IE and Firefox (Firefox supports SVG clip paths only).




回答2:


If you need full browser support, And you want the inner part to be transparent, and you want a CSS only solution ... you can not use a gradient. You need to fake it whit shadows

.test {
  width: 200px;
  height: 80px;
  border-radius: 40px;
  position: relative;
  overflow: hidden;
  color: white;
  font-size: 50px;
  padding-left: 30px;
}  

.test:after  {
  content: "";
  position: absolute;
  
  width: calc(100% - 10px);  
  height: calc(100% - 10px);  
  top: 0px;
  right: 0px;
  bottom: 0px;
  left: 0px;
  margin: auto;
  border-radius: inherit;
  box-shadow: -20px 0px 10px 5px rgba(250, 250, 20, 1),
               20px 0px 10px 10px rgba( 20, 250, 200, 1);
}

body {
  background: radial-gradient(circle, black, darkgrey);
}
<div class="test">TEST</div>


来源:https://stackoverflow.com/questions/35326630/is-there-a-way-to-create-a-button-or-div-with-a-border-that-has-a-gradient-and

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!