Как создать гладкую изогнутую маску SVG для правого верхнего угла блока?

Я пытаюсь создать блок с гладким изогнутым вырезом в правом верхнем углу, как показано на рисунке ниже:

На данный момент моя реализация выглядит так:

Как видите, текущая кривая не такая плавная, как хотелось бы — по сути, это не кривая, а квадрат с прямыми углами. Вот мой текущий код:

body {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  margin: 0;
  background-color: #f0f0f0;
  font-family: Arial, sans-serif;
}

.curved-block {
  width: 300px;
  background-color: white;
  border-radius: 10px;
  box-shadow: 0 2px 10px rgba(0,0,0,0.1);
  position: relative;
  overflow: hidden;
  padding: 5px;
}

.curved-block::after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  width: 40px;
  height: 40px;
  background-color: #f0f0f0;
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 40 40'%3E%3Cpath d='M0 0 h25 c5 0, 10 0, 13 3 s2 7, 2 12 v25 h-40 z' fill='%23000000'/%3E%3C/svg%3E");
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' viewBox='0 0 40 40'%3E%3Cpath d='M0 0 h25 c5 0, 10 0, 13 3 s2 7, 2 12 v25 h-40 z' fill='%23000000'/%3E%3C/svg%3E");
  mask-size: cover;
  -webkit-mask-size: cover;
}

.icon {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 23px;
  height: 23px;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 16px;
  font-weight: bold;
  background-color: #0056b3;
  border-radius: 50%;
  color: white;
  z-index: 2;
}
<div class = "curved-block">
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
  <span class = "icon">+</span>
</div>

Я изо всех сил пытаюсь добиться более плавной и естественной кривой в маске SVG. Как я могу изменить путь SVG, чтобы создать кривую, которая больше похожа на кривую на желаемом результирующем изображении? Заранее благодарим вас за ваши предложения.

Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Travel Booking Angular Template один из лучших Travel & Tour booking template in the world. 30+ валидированных HTML5 страниц, которые помогут...
0
0
51
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я сделал это здесь: https://css-shape.com/inverted-radius/

Вы можете легко скопировать код и настроить переменные:

.inverted-radius {
  --r: 15px; /* the radius */
  --s: 30px; /* the size of the corner*/
  
  height: 150px;
  margin: 10px;
  background: #3FB8AF;
  border-radius: var(--r);
  --_m:/calc(2*var(--r)) calc(2*var(--r))
    radial-gradient(#000 70%,#0000 72%) no-repeat;
  mask:
    right calc(var(--s) + var(--r)) top var(--_m),
    right calc(var(--s) + var(--r)) var(--_m),
    radial-gradient(var(--s) at 100% 0,#0000 99%,#000 101%) 
     calc(-1*var(--r)) var(--r) no-repeat,
    conic-gradient(at calc(100% - var(--s) - 2*var(--r)) calc(var(--s) + 2*var(--r)),
     #0000 25%,#000 0);
}
<div class = "inverted-radius"></div>
Ответ принят как подходящий

Поскольку вы используете равномерно закругленные углы, вы также можете комбинировать CSS clip-path с фильтром «слизь» SVG.

body {
  font-family: Arial, sans-serif;
  margin: 0;
  background-color: #f0f0f0;
  padding: 3em;
}

:root{
  --icon-space: 2em;
  --drop-shadow: drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.75))
}

.curved-block-outer {
  position: relative;
}

.curved-block {
  background-color: #fff;
  padding: 0.5em 2.5em 0.5em 0.5em;
  clip-path: polygon( 0% 0%, calc(100% - var(--icon-space)) 0%, calc(100% - var(--icon-space)) var(--icon-space), 100% var(--icon-space), 100% 100%, 0% 100%);
}

/* round corners via SVG filter; add drop shadow */
.curved-block-filter {
  filter: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><filter id='goo'><feGaussianBlur in='SourceGraphic' stdDeviation='7.5' result='blur'/><feColorMatrix in='blur' mode='matrix' values='1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 19 -9' result='goo'/><feComposite in='SourceGraphic' in2='goo' operator='atop'/></filter></svg>#goo") var(--drop-shadow);
}

.icon {
  position: absolute;
  right: 0;
  top: 0;
  z-index: 10;
  width: 1.5em;
  height: 1.5em;
  display: block;
  text-align: center;
  font-size: 1em;
  line-height: 1.6em;
  font-weight: bold;
  background-color: #0056b3;
  border-radius: 50%;
  color: #fff;
  filter: var(--drop-shadow);
}
<div class = "curved-block-outer ">
  <span class = "icon">+</span>
  <div class = "curved-block-filter">
    <div class = "curved-block">
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
    </div>
  </div>
</div>

Мы в основном

  • рисование многоугольника с 6 вершинами в относительных единицах измерения
  • примените фильтр SVG, чтобы округлить рендеринг этого многоугольника

К сожалению, нам нужны некоторые дополнительные элементы-обертки, иначе мы не сможем применить тень, или кнопка «плюс» также будет затронута фильтрами.

Гу фильтр

Вы можете сослаться на фильтр, встроив SVG в свой HTML.

<svg class = "flt_svg">
    <filter id = "goo">
      <feGaussianBlur in = "SourceGraphic" stdDeviation = "7.5" result = "blur" />
      <feColorMatrix in = "blur" mode = "matrix" values = "1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 19 -9" result = "goo" />
      <feComposite in = "SourceGraphic" in2 = "goo" operator = "atop" />
    </filter>
</svg>

и примените его в CSS следующим образом:

filter: url("#goo")

или вы можете закодировать SVG в dataURL и встроить его непосредственно в CSS.

filter: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><filter id='goo'><feGaussianBlur in='SourceGraphic' stdDeviation='7.5' result='blur'/><feColorMatrix in='blur' mode='matrix' values='1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 19 -9' result='goo'/><feComposite in='SourceGraphic' in2='goo' operator='atop'/></filter></svg>#goo")

Значение stdDeviation='7.5' указывает радиус границы/закругления.

См. также

Спасибо, отличный ответ и очень познавательно. Спасибо за статьи и пояснения, в будущем смогу проделывать подобные трюки.

Alex Nikolsky 27.08.2024 10:59

Другие вопросы по теме