Home > Mobile >  Is it possible to make a crosshair with a single div?
Is it possible to make a crosshair with a single div?

Time:05-26

I'm trying to create a cross hair like this:

<div ></div>

enter image description here

using a single element and pure css?

I thought of using ::after & ::before along with the div
but that would only result in 3 bars whereas the image has 4 bars,

I'm not sure if it's even possible but maybe I missed something?

Edit

btw the transparency of the crosshair as a whole changes to see stuff behind it

Edit 2

on @tacoshy request in the comments I'm also adding my "research"

:root{
  --bar_thickness:0.5rem;
  --bar_length:5rem;
}

.crosshair::before{
  content:"";
  display:block;
  background-color:black;
  height:var(--bar_length);
  width:var(--bar_thickness);
  position:relative;
  transform:rotate(90deg);
}

.crosshair {
  margin:3rem;
  background-color:black;
  height:var(--bar_length);
  width:var(--bar_thickness);
}

.crosshair::after{
  content:"";
  display:block;
  background-color:white;
  height:calc( var(--bar_length) * 0.4);
  width:calc( var(--bar_length) * 0.4);
  position:relative;
  bottom:50%;
  left:50%;
  transform:translate(-50%,-50%)
}
<div ></div>

but the problem with my approach is when I need it to be transparent as mentioned in the first edit it fails as such:

:root{
  --bar_thickness:0.5rem;
  --bar_length:5rem;
}

.crosshair::before{
  content:"";
  display:block;
  background-color:black;
  height:var(--bar_length);
  width:var(--bar_thickness);
  position:relative;
  transform:rotate(90deg);
}

.crosshair {
  
  position:absolute;
  opacity:50%;
  margin:3rem;
  background-color:black;
  height:var(--bar_length);
  width:var(--bar_thickness);
}

.crosshair::after{
  content:"";
  display:block;
  background-color:white;
  height:calc( var(--bar_length) * 0.4);
  width:calc( var(--bar_length) * 0.4);
  position:relative;
  bottom:50%;
  left:50%;
  transform:translate(-50%,-50%)
}
<div id="background" style="background-color:red;height:10rem;width:10rem">
  <div ></div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitatio

</div>

CodePudding user response:

You can do something with box-shadow:

#el {
  position: relative;
}

#el::after, #el::before {
  content: "";
  background: black;
  border-radius: 2px;
  position: absolute;
}

#el::after {
  left: 30px;
  width: 10px;
  height: 20px;
  box-shadow: 0 50px black;
}

#el::before {
  top: 30px;
  width: 20px;
  height: 10px;
  box-shadow: 50px 0 black;
}
<div id=el></div>

Or you might use the border instead of box-shadow:

#el {
  position: relative;
  margin-top: 40px;
  height: 10px;
  width: 30px;
  border-left: 20px solid black;
  border-right: 20px solid black;
}

#el::after, #el::before {
  content: "";
  width: 10px;
  height: 20px;
  background: black;
  position: absolute;
  left: 10px;
}

#el::before {
  top: -30px;
}

#el::after {
  top: 20px;
}
<div id=el></div>

Or use only the ::before and ::after borders:

#el {
  position: relative;
}

#el::after, #el::before {
  content: "";
  position: absolute;
  box-sizing: border-box;
}

#el::before {
  width: 10px;
  height: 70px;
  left: 30px;
  border-top: 20px solid black;
  border-bottom: 20px solid black;
}

#el::after {
  width: 70px;
  height: 10px;
  top: 30px;
  border-left: 20px solid black;
  border-right: 20px solid black;
}
<div id=el></div>

Or use gradients instead of borders:

#el {
  position: relative;
}

#el::after, #el::before {
  content: "";
  position: absolute;
}

#el::before {
  width: 10px;
  height: 70px;
  left: 30px;
  background: linear-gradient(0deg, rgba(0,0,0,1) 28.57%, rgba(0,0,0,0) 28.57%, rgba(0,0,0,0) 71.43%, rgba(0,0,0,1) 71.43%);
}

#el::after {
  width: 70px;
  height: 10px;
  top: 30px;
  background: linear-gradient(90deg, rgba(0,0,0,1) 28.57%, rgba(0,0,0,0) 28.57%, rgba(0,0,0,0) 71.43%, rgba(0,0,0,1) 71.43%);
}
<div id=el></div>

CodePudding user response:

I'd prefer a shorter solution using box-shadow and no ::before or ::after pseudo elements. If the div needs to encapsulate the whole crosshair, then this styling could also be applied on the ::before pseudo element.

.crosshair{
  margin:30px;
  width:5px;
  height:5px;
  box-shadow: 15px 0,20px 0,25px 0,-15px 0,-20px 0,-25px 0,0 15px,0 20px,0 25px,0 -15px,0 -20px,0 -25px
}
<div ></div>

CodePudding user response:

A solution with 3 property and one gradient:

.cross {
  width:100px;
  aspect-ratio:1;
  --c: linear-gradient(#000 0 0) 50%;
  background:
    var(--c)/34% 10% space no-repeat,
    var(--c)/10% 34% no-repeat space;
}
<div ></div>

And another one:

.cross {
  --b: 30%; /* length */
  --t: 10%; /* thickness */

  width: 100px;
  aspect-ratio: 1;
  --c: #000 var(--b),#0000 0 calc(100% - var(--b)),#000 0;
  background:
    linear-gradient( 0deg,var(--c)) 50%/var(--t) 100% no-repeat,
    linear-gradient(90deg,var(--c)) 50%/100% var(--t) no-repeat;
}
<div ></div>

CodePudding user response:

Using characters for the bars works and is transparent. But you may as well use a font that contains the crosshair then, much like how FontAwesome does icons. FontAwesome probably contains a crosshair.

.crosshair {
    position: relative;
}

.crosshair:before, .crosshair:after {
    content: "— —";
    display: inline-block;
    width: 3em;
    height: 3em;
    line-height: 2.9em;
    text-align: center;
    position: absolute;
    top: 0;
    left: 0;
}

.crosshair:after {
    transform-origin: center;
    transform: rotate(90deg);
}
<div ></div>

  • Related