Edge in intercession between 2 elements - CSS

3

I'm creating the following menu:

butIcannotcreatethisborder:

HowcanIcreateitwithCSS?

.m{
  position: fixed;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  background: #aaa;
}
.a{
  background: #777;
  position: relative;
  padding: 0 1rem;
  margin-top: 1rem;
  margin-left: 1rem;
  height: 2rem;
  border-radius: .5rem .5rem 0 0
}
.b{
  position: absolute;
  width: 5rem;
  background: #777;
  top: 2rem;
  left: 0;
  border-radius: 0 .5rem .5rem .5rem;
  padding: 1rem;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet"/>

<div class='m d-flex flex-row'>
  <div class='a'>
    <span>a</span>
    <div class='b'>
      <div class='d-flex flex-column'>
        <div><span>a1</span></div>
        <div><span>a2</span></div>
        <div><span>a3</span></div>
        <div><span>a4</span></div>
        <div><span>a5</span></div>
      </div>
    </div>
  </div>
</div>

See the code in the Fiddle

    
asked by anonymous 23.08.2018 / 16:25

4 answers

4

With CSS only, you can use the ::before and ::after pseudo-elements, however this solution works only if the page background is solid.

In your case, because it is a gradient, it is possible only with ::after using border-radius and box-shadow of it.

The theory is to put ::after out of the parent and apply border-radius as needed to get the desired curve effect and use box-shadow to fill the outside of the border with the same tab color.

You have the code here:

.m{
  position: fixed;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  background: #aaa;
}
.a{
  background: #777;
  position: relative;
  padding: 0 1rem;
  margin-top: 1rem;
  margin-left: 1rem;
  height: 2rem;
  border-radius: .5rem .5rem 0 0
}
.a::after {
  content: " ";
  position: absolute;
  right: -.5rem;
  bottom: 0;
  width: .5rem;
  height: .5rem;
  
  border: .1rem solid transparent;
  border-bottom-left-radius: 1rem;
  border-width: 0 0 .2rem .2rem;
  box-shadow: -.1rem 2px 0 #777;
}

/* ou usando o :before e :after - so funciona com fundos solidos */
/*.a::before {
  content: "";
  background: #777;
  position: absolute;
  right: -.5rem;
  bottom: 0rem;
  width: .5rem;
  height: .5rem;
}
.a::after {
  content: "";
  position: absolute;
  right: -1rem;
  bottom: 0rem;
  width: 1rem;
  height: 1rem;
  border-radius: 100%;
  background-color: #aaa;
}
*/

.b{
  position: absolute;
  width: 5rem;
  background: #777;
  top: 2rem;
  left: 0;
  border-radius: 0 .5rem .5rem .5rem;
  padding: 1rem;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet"/>
<div class='m d-flex flex-row'>
  <div class='a'>
    <span>a</span>
    <div class='b'>
      <div class='d-flex flex-column'>
        <div><span>a1</span></div>
        <div><span>a2</span></div>
        <div><span>a3</span></div>
        <div><span>a4</span></div>
        <div><span>a5</span></div>
      </div>
    </div>
  </div>
</div>

See the code working in JSFiddle

    
23.08.2018 / 17:18
2

One way to solve this is to use svg. Here's an example.

index.html

<html><head><linkrel="stylesheet" href="style.css">
  </head>
  <body>
    <div id="left">
      This is the content on the left side
      <div class="fancy-join">
    <div class="stroke"></div>
      </div>
    </div>
    <div id="right">
      This is the content on the right side
    </div>
  </body>
</html>

circle-bottom-right.svg

<svg baseProfile="full" height="10" version="1.1" width="10" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <path fill="white" stroke="white" stroke-width="1" d="M5,9A4,4 0 0,0 9,5L10,5L10,10L5,10Z"/>
  <path fill="none" stroke="#ccc" stroke-width="1" stroke-linecap="square" d="M5,9A4,4 0 0,0 9,5"/>
</svg>

circle-top-right.svg

<svg baseProfile="full" height="10" version="1.1" width="10" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <path fill="white" stroke="white" stroke-width="1" d="M9,5A4,4 0 0,0 5,1L5,0L10,0L10,5Z"/>
  <path fill="none" stroke="#ccc" stroke-width="1" stroke-linecap="square" d="M9,5A4,4 0 0,0 5,1"/>
</svg>

style.css

body {
  background-color: #eee;
}
#left, #right {
  margin: 10px;
  width: 300px;
  float: left;
  padding: 0.5em;
  border: 1px solid #ccc;
  border-radius: 4px;
  background-color: white;
}
#left {
  margin-top: 80px;
  margin-right: 0px;
  padding-right: 0em;
  border-right: none;
  border-top-right-radius: 0px;
  height: 1em;
  border-bottom-right-radius: 0px;
}
#right {
  margin-left: 0px;
  height: 200px;
}


.fancy-join{
  position:relative;
  width:0;
  height:0;
  left:100%;
  top:-1.5em;
  z-index:2;
}
.fancy-join .stroke{
  position:absolute;
  top: -2px;
  width:1px;
  height:2.1em;
  background-color:#fff;
}
.fancy-join .stroke:after{
  content:"";
  position:absolute;
  left:-9px;
  top:-10px;
  background-image:url("circle-bottom-right.svg");
  background-repeat:no-repeat;
  z-index:4;
  width:10px;
  height:10px;
}
.fancy-join .stroke:before{
  content:"";
  position:absolute;
  left:-9px;
  bottom: -8px;
  background-image:url("circle-top-right.svg");
  background-repeat:no-repeat;
  z-index:4;
  width:10px;
  height:10px;
}
    
23.08.2018 / 17:10
1

CSS Solution

The solution to this problem can only be done with CSS , using two :: after pseudo-elements and :: before pseudo- strong> .a

Analysis code below:)

.a::after,
.a::before {
  content: "";
  display: block;
  width: 10px;
  height: 10px;
  position: absolute;  
  z-index: 1;
  border-radius: 50%;
}
.a::after {
  background: red;
  right: -10px;
  bottom: 0px;
}
.a::before {
  background: #000;  
  right: -5px;
  bottom: -5px;
}
.m{
  position: fixed;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  background: #aaa;
}
.a{
  background: #000;
  position: relative;
  padding: 0 1rem;
  margin-top: 1rem;
  margin-left: 1rem;
  height: 2rem;
  border-radius: .5rem .5rem 0 0
}
.b{
  position: absolute;
  width: 5rem;
  background: #000;
  top: 2rem;
  left: 0;
  border-radius: 0 .5rem .5rem .5rem;
  padding: 1rem;
}

<div class='m d-flex flex-row'>
  <div class='a'>
    <span>a</span>
    <div class='b'>
      <div class='d-flex flex-column'>
        <div><span>a1</span></div>
        <div><span>a2</span></div>
        <div><span>a3</span></div>
        <div><span>a4</span></div>
        <div><span>a5</span></div>
      </div>
    </div>
  </div>
</div>

link

    
23.08.2018 / 17:37
1

Another simple way to do this is with radial-gradient going transparent to the color you need.

You can create a ::after pseudo element and place it in radial-gradient . The way I did no matter what Tab text size , everything will always be aligned (ou vc pode colocar um valor fixo se quiser) , you just need to set the values of .container if you want ...  To understand better see the code below

body {
  background-image: linear-gradient(45deg, red, blue);
  background-repeat: no-repeat;
}
.tab {
  box-sizing: border-box;
  padding: 16px;
  background-color: #fff;
  border-radius: 10px 10px 0 0;
  position: relative;
  display: inline-block;
  text-align: center;
}
.tab::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 100%;
  width: 20px;
  height: 20px;
  background-image: radial-gradient(circle at 100% 0%, transparent 0px, transparent 19.5px, #fff 20.5px);
  background-repeat: no-repeat;
}
.txt {
  height: 120px;
  background-color: #fff;
  border-radius: 0 10px 10px 10px;
  box-sizing: border-box;
  padding: 10px;
}
.container {
  padding: 20px;
  box-sizing: border-box;
  width: 50%;
  float: left;
}
<div class="container">
  <div class="tab">tab</div>
  <div class="txt">texto</div>
</div>

<div class="container">
  <div class="tab">tgdfg dfgdfab</div>
  <div class="txt">texto</div>
</div>
    
25.08.2018 / 16:14