CSS, чтобы создать изогнутый угол между двумя элементами? - PullRequest
29 голосов
/ 05 января 2011

Мой пользовательский интерфейс имеет неупорядоченный список слева. Когда выбран элемент списка, справа от него появляется div. Я хотел бы иметь изогнутый внешний угол , где встречаются <li> и <div>. Некоторые люди называют это отрицательным радиусом границы или перевернутым углом . Смотрите белую стрелку на изображении ниже.

sample image

Чтобы расширить синий <li> до края <ul>, я планирую сделать что-то вроде этого:

li { 
    right-margin: 2em; 
    border-radius: 8px; 
}

li.active { 
    right-margin: 0; 
    border-bottom-right-radius: 0; 
    border-top-right-radius: 0;
}

Есть ли лучший способ расширить <li> до края <ul>? Очевидно, я также включу CSS для webkit и границы радиуса Mozilla.

Главное, в чем я не уверен, это то, что внешний угол под правым нижним углом активного <li>. У меня есть некоторые идеи, но они кажутся хаки. Есть предложения?

Обратите внимание, что <ul> обозначен серым, но в реальном дизайне он будет белым. Кроме того, я планирую использовать Javascript для правильного позиционирования <div>, когда выбран <li>.

Ответы [ 6 ]

11 голосов
/ 05 января 2011

Ну, как оказалось, мне удалось решить проблему самостоятельно. Я взломал демо - заценил .

По сути, требуется несколько дополнительных элементов DOM и значительное количество CSS. И, как упоминалось в ссылке, предоставленной @Steve, необходим сплошной фон. Я не верю, что есть какой-либо способ сделать это на градиентном фоне или другом шаблоне.

Я закончил с HTML, как это:

ul.selectable {
  padding-top: 1em;
  padding-bottom: 1em;
  width: 50%;
  float: left;
}
ul.selectable li {
  margin: 0 3em 0 4em;
  border-radius: 8px;
  -webkit-border-radius: 8px;
  -khtml-border-radius: 8px;
  -moz-border-radius: 8px;
}
ul.selectable li.active {
  margin-right: 0;
}
ul.selectable li.active dl {
  background-color: #4f9ddf;
}
ul.selectable li dt {
  background-color: #dfd24f;
  padding: 1em;
  margin-left: -2em;
  margin-right: -2em;
  -webkit-border-radius: 8px;
  -khtml-border-radius: 8px;
  -moz-border-radius: 8px;
  border-radius: 8px;
}
ul.selectable li dd {
  padding: 0.25em;
  background-color: #fff;
}
ul.selectable li.active dt {
  background-color: #4f9ddf;
  margin-right: 0;
  -webkit-border-top-right-radius: 0;
  -webkit-border-bottom-right-radius: 0;
  -khtml-border-top-right-radius: 0;
  -khtml-border-bottom-right-radius: 0;
  -moz-border-radius-topright: 0;
  -moz-border-radius-bottomright: 0;
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}
ul.selectable li.active dd.top {
  -webkit-border-bottom-right-radius: 8px;
  -khtml-border-bottom-right-radius: 8px;
  -moz-border-radius-bottomright: 8px;
  border-bottom-right-radius: 8px;
}
ul.selectable li.active dd.bot {
  -webkit-border-top-right-radius: 8px;
  -khtml-border-top-right-radius: 8px;
  -moz-border-radius-topright: 8px;
  border-top-right-radius: 8px;
}
div.right {
  float: left;
  padding-top: 3em;
  width: 50%;
}
div.content {
  height: 15em;
  width: 80%;
  background-color: #4f9ddf;
  padding: 1em;
  -webkit-border-radius: 8px;
  -khtml-border-radius: 8px;
  -moz-border-radius: 8px;
  border-radius: 8px;
}
<ul class="selectable">
  <li>
    <dl>
      <dd class="top"></dd>
      <dt>Title</dt>
      <dd class="bot"></dd>
    </dl>
  </li>
  <li class="active">
    <dl>
      <dd class="top"></dd>
      <dt>Title</dt>
      <dd class="bot"></dd>
    </dl>
  </li>
  <li>
    <dl>
      <dd class="top"></dd>
      <dt>Title</dt>
      <dd class="bot"></dd>
    </dl>
  </li>
</ul>
<div class="right">
  <div class="content">This is content</div>
</div>

Я не оптимизировал ни один из CSS, так как только что взломал его вместе. Но, возможно, это поможет кому-то еще. Я проверял это только в Google Chrome на Mac OSX.

5 голосов
/ 14 июля 2012

Чистое решение (меньше кода и Допустимый градиент фона )

См. Скрипку (или еще ), которая использует этот html:

<ul class="selectable">
    <li>Title</li>
    <li class="active">Title</li>
    <li>Title</li>
    <li>Title</li>
</ul>
<div class="right">
    <div class="content">This is content</div>
</div>

И это css (ключ должен позволить border-radius и border-width на псевдоэлементах сделать для вас перевернутый круг; я пропустил код gradient):

ul.selectable {
    padding-top: 1em;
    padding-bottom: 1em;
    width: 50%;
    float: left;
}
ul.selectable li {
    margin: 1em 1em 1em 2em;
    padding: 1em;
    border-radius: 8px;
    -webkit-border-radius: 8px;
    -khtml-border-radius: 8px;
    -moz-border-radius: 8px;
    background-color: #dfd24f;
    position: relative;
}
ul.selectable li.active {
    margin-right: 0;
    background-color: #4f9ddf;
    -webkit-border-top-right-radius: 0;
    -webkit-border-bottom-right-radius: 0;
    -khtml-border-top-right-radius: 0;
    -khtml-border-bottom-right-radius: 0;
    -moz-border-radius-topright: 0;
    -moz-border-radius-bottomright: 0;
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}

ul.selectable li.active:before,
ul.selectable li.active:after {
    content: '';
    position: absolute;
    left: 100%; /* I use this instead of right: 0 to avoid 1px rounding errors */
    margin-left: -8px; /* I use this because I am using left: 100% */
    width: 8px;
    height: 8px;
    border-right: 8px solid #4f9ddf;
    z-index: -1;    
}

ul.selectable li.active:before {
    top: -8px;
    border-bottom: 8px solid  #4f9ddf;
    -webkit-border-bottom-right-radius: 16px;
    -khtml-border-bottom-right-radius: 16px;
    -moz-border-radius-bottomright: 16px;
    border-bottom-right-radius: 16px;
}
ul.selectable li.active:after {
    bottom: -8px;
    border-top: 8px solid  #4f9ddf;
    -webkit-border-top-right-radius: 16px;
    -khtml-border-top-right-radius: 16px;
    -moz-border-radius-topright: 16px;
    border-top-right-radius: 16px;
}
div.right {
    float: left;
    padding-top: 3em;
    width: 50%;
}
div.content {
    height: 15em;
    width: 80%;
    background-color: #4f9ddf;
    padding: 1em;
    -webkit-border-radius: 8px;
    -khtml-border-radius: 8px;
    -moz-border-radius: 8px;
    border-radius: 8px;
}
3 голосов
/ 07 января 2011

Я придумал решение, которое требует меньше разметки. Таким образом, вместо использования полей используются белые округленные границы, а затем мы размещаем активный li позади белых округленных границ для достижения эффекта инвертированного радиуса границы.

http://jsfiddle.net/zrMW8/

<ul class="selectable">
    <li>
        <a href="#">Title</a>
    </li>
    <li class="active">
        <a href="#">Title</a>
    </li>
    <li>
        <a href="#">Title</a>
    </li>
    <li>
        <a href="#">Title</a>
    </li>
</ul>
<div class="right">
    <div class="content">This is content</div>
</div>

И меньше CSS тоже! (это сгибание ума):

a { color: #000; text-decoration: none;}

ul.selectable {
    padding: 1em 1em;
    width: 40%;
    float: left;
}

ul.selectable li {
    margin:  -1em 0 0 0;
    border-radius: 8px;
    -webkit-border-radius: 8px;
    -khtml-border-radius: 8px;
    -moz-border-radius: 8px;
    border: solid #fff 1em;
    position: relative;
}

ul.selectable li a {
   background-color: #dfd24f;
    padding: 1em;
    display: block;
       border-radius: 8px;
    -webkit-border-radius: 8px;
    -khtml-border-radius: 8px;
    -moz-border-radius: 8px;
}

ul.selectable li.active {
    margin: -1em -1em -1em 1em;
    border: solid #4f9ddf 1em;
    border-left: solid #fff 1em;
    background-color: #4f9ddf;
    position: static;
}

ul.selectable li.active a {
    margin: 0 0 0 -1em;
    border-left: solid #4f9ddf 1em;
    background-color: #4f9ddf;
    position: static;
    text-indent: -1em;
}

div.right {
    float: left;
    padding-top: 3em;
    width: 50%;
    margin-left: -1em;
}
div.content {
    height: 15em;
    width: 80%;
    background-color: #4f9ddf;
    padding: 1em;
    -webkit-border-radius: 8px;
    -khtml-border-radius: 8px;
    -moz-border-radius: 8px;
    border-radius: 8px;
}

Сказать по правде, я не уверен, что это лучшая версия, она делает градиентные / фоновые изображения легкими (по крайней мере, для неактивных li), но вы не можете применить изображение / градиентный фон к телу. Это также «плохая магия» в том смысле, что она работает не интуитивно.

0 голосов
/ 14 июля 2012

Этот хороший Обратный радиус границы в руководстве по CSS может помочь.Объясняет, как сделать обратный радиус границы для вкладок.Но его можно легко адаптировать для оптимизации вашего CSS, поскольку он использует :after вместо создания слишком большого количества дополнительных элементов.

0 голосов
/ 05 января 2011

Для того, чтобы сделать это над не твердым bg, я не думаю, что вы можете сделать это с CSS, но вы можете использовать canvas или SVG с тем же эффектом - не совсем то, что вы просили, хотя.

Однако, как представляется, существует предложение для отрицательного радиуса границы , которое решило бы проблему. Может быть, когда-нибудь, верно.

0 голосов
/ 05 января 2011
...