Splitting a square into four triangles using CSS styling

My current challenge involves creating a square comprised of 4 triangles of equal size, each with hover events. Here is the CSS I'm using to create the triangles:

.right, left, .top, .bottom {
    position: relative;
    width: 26px;
}

.right:before{
  position: absolute;
  display: inline-block;
  border-top: 26px solid transparent;
  border-right: 26px solid #eee;
  border-bottom: 26px solid transparent;
  left: 26px;
  top: 0px;
  content: '';
}

The issue I'm facing is that the triangles are stacking on top of each other, making only one triangle hoverable at a time. You can view an example here.

Currently, only the bottom triangle (hover at the bottom of the square) is responsive to hovering. What am I doing wrong? Are there any alternative methods to achieve this effect?

Answer №1

One key factor causing the hover effect to only work on the bottom triangle and not the others is due to the stacking order of the containers. The container of the bottom triangle appears above the containers of the other three, which limits the hover interaction to just that area.

Although utilizing the border trick generates triangle shapes, the underlying form remains a square. The appearance of triangles is achieved by making the adjacent borders transparent. Consequently, hovering over the shape targets the transparent regions of the bottom triangle rather than triggering the other triangles' respective hover events.

A suggestion would be to use SVG for such designs, although creating these shapes with CSS alone is feasible given the simplicity of this shape.

SVG:

In an SVG context, multiple triangles within a square can be created using polygon elements, each being individually hoverable. For distinct target links, enclosing the polygons in an a (anchor) tag is recommended.

The example includes anchor implementation for one triangle only

.square {
  height: 400px;
  width: 400px;
  overflow: hidden;
}
svg {
  height: 100%;
  width: 100%;
}
polygon {
  fill: aliceblue;
  stroke: crimson;
  stroke-linejoin: round;
}
polygon:hover {
  fill: cornflowerblue;
}
<div class='square'>
  <svg viewBox='0 0 100 100'>
    <a xlink:href='http://google.com'>
      <polygon points='5,5 50,50 95,5' />
    </a>
    <polygon points='5,5 50,50 5,95' />
    <polygon points='5,95 50,50 95,95' />
    <polygon points='95,5 50,50 95,95' />
  </svg>
</div>


CSS:

This CSS solution modifies the provided answer from here by web-tiki. A unique response is necessary due to the simplicity of the current shape, requiring less complexity compared to the initial case.

The square is divided into four identical hoverable triangles through the following steps:

  • The parent container, a square, features borders on all sides. This structural choice helps avoid the challenges associated with diagonal line placement in CSS-based triangles.
  • Four child elements are added within the container, each sized using Pythagoras theorem computation. These elements are positioned with their top left corner at the square's center, aiding in rotation effects.
  • All child elements undergo rotations to depict triangular shapes, with transform-origin set to top left for axis alignment with the square’s center when rotating.
  • The parent has overflow: hidden to conceal half of each triangle outside its boundaries.
  • Note that adding text directly to the triangles may pose challenges due to their rotated nature. Text content should ideally be placed in separate child elements counter-rotated appropriately.

Note: The demo script uses prefix-free library to eliminate browser prefixes requirements.

.square {
  position: relative;
  height: 200px;
  width: 200px;
  border: 2px solid crimson;
  overflow: hidden;
  transition: all 1s;
}
.top,
.left,
.right,
.bottom {
  position: absolute;
  height: calc(100% / 1.414);
  width: calc(100% / 1.414);
  top: 50%;
  left: 50%;
  border: 1px solid crimson;
  transform-origin: 0% 0%;
}
.right {
  transform: rotate(-45deg);
}
.bottom {
  transform: rotate(45deg);
}
.top {
  transform: rotate(-135deg);
}
.left {
  transform: rotate(135deg);
}
.square > div:hover {
  background: tomato;
}

/*Just for demo*/

.square:hover{
  height: 300px;
  width: 300px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='square'>
  <div class="top"></div>
  <div class="right"></div>
  <div class="bottom"></div>
  <div class="left"></div>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Ensure consistent element heights within adjacent columns using CSS

My template looks like this: I am trying to keep the same height between each item in both columns, where the height is determined by the tallest item in each column when they are placed side by side. But on smaller screens with a width of 100%, I want ea ...

How can I adjust iframe content to fit properly on a mobile device screen?

I am facing a challenge where I need to embed an iframe into an external website over which I have no control. The only thing I can specify is the size of the iframe on my own website. My goal is to ensure that the content within the iframe adjusts to fit ...

Move divs that are currently not visible on the screen to a new position using CSS animations

Upon entering the site, I would like certain divs to animate from an offscreen position. I came across this code snippet: $( document ).ready(function() { $('.box-wrapper').each(function(index, element) { setTimeout(function(){ ...

Inquiring about paint-order support for HTML elements using @supports

For those looking to create boldly stroked texts in Firefox and Safari, using paint-order and text-stroke (or the prefixed -webkit-text-stroke) is the way to go. Here's an example: h1 { -webkit-text-stroke: 5px red; paint-order: stroke fil ...

Error: The value for $regex must be in the form of a string

Encountering a problem with an error in the Console: { [MongoError: $regex has to be a string] name: 'MongoError', message: '$regex has to be a string', waitedMS: 0, ok: 0, errmsg: '$regex has to be a string', code ...

Tips for Controlling an Absent Search Bar in the HTML Source Code with Selenium

I'm attempting to automate searches using Selenium in Java. Upon inspecting the search bar on the page, I noticed that it has an id of searchBox and a name of q, which could be helpful. However, these properties are not visible in the HTML when viewi ...

The issue regarding the fixed table layout bug in Firefox

Upon testing Firefox 5, it has come to my notice that an additional pixel of space is being added between the right column and the table border due to this particular piece of code: <style type="text/css"> table { border: 1px s ...

Display various items using only one EJS scriptlet tag

I'm currently facing a challenge with rendering two objects using EJS. I am curious to know if it is feasible to render them both within the same pair of scriptlet tags or if they need to be rendered separately? So far, I have been able to successful ...

What steps should be taken to prevent divs from overlapping a centrally positioned, unchanging div when the browser is resized

Looking to create a layout with two columns, featuring a fixed sidebar on the left and centering the main content area. The goal is for the centered content to remain in place when resized and not move further left than where it touches the nav bar (left: ...

What is causing the div to not update until the for loop is completed?

I have an HTML page where I am trying to update a div while a for loop is running. However, the div does not update until after the loop finishes. Why is this happening? <!DOCTYPE html> <html> <body> ...

Learning how to effectively incorporate two matSuffix mat-icons into an input field

I'm currently experiencing an issue where I need to add a cancel icon in the same line as the input field. The cancel icon should only be visible after some input has been entered. image description here Here's the code I've been working on ...

There seems to be an issue with the <mat-form-field> where normal input functions correctly, but encounters an error when trying to use mat

I've searched through other inquiries, but none have provided the solution I am looking for. <mat-form-field> <mat-select matInput placeholder="Favorite food"> <mat-option *ngFor="let food of foods" [value]="food.value"> ...

Jumbling a word by shuffling its letters into a random order

The objective of the program is to take the word you input into a box, split it into an array of letters, and then shuffle them. Following that, it should capitalize the first letter and lowercase the rest before displaying the result in the same box. I a ...

Animating an image into a Vue.js div

Is it possible to create a dynamic image animation using Vue.js? I am looking to create an interactive "Add to Cart" experience where when a user clicks on the button, the product's image smoothly glides over to the shopping cart icon before fading a ...

Troubleshooting a Cache Issue in Your Next.js Application

Whenever I attempt to run 'npm run build', an error crops up that seems to be linked to the css and fonts. Unfortunately, I am unsure of how to tackle this problem. It's perplexing as the app functions perfectly fine in development mode. Th ...

Execute an AJAX post request to the identical PHP page (utilizing the Jquery Form Plugin)

I am in the process of developing a new web interface using JavaTMP, an AJAX-based admin template. After spending time understanding its functionality, I have created a page with a form to allow users to create projects within my software. Typically, creat ...

Graphic background integrated into form input

Is it advisable to create colored shapes in Illustrator, export them as SVG files, and then embed input tags or textareas within these shapes to allow users to enter text? Are there alternative methods we could use for this functionality? ...

Tips for effectively showcasing div elements

https://jsfiddle.net/qz8hL574/1/ for (var key in table) { if (table.hasOwnProperty(key)) { $('<div class="element"></div>').appendTo('#list'); document.getElementsByClassName("element")[key].innerHTML = ...

Utilizing Isotope JS on your Wordpress website

I'm in the process of integrating the .js plugin, Isotope, into my Wordpress installation. It should be positioned at the bottom of this page: To achieve this, I am referring to an example on codepen: https://codepen.io/desandro/pen/mEinp The script ...

What is the best solution for adjusting spacing in justified text columns within bootstrap?

As I work on creating a div with two columns, I am facing an issue with maintaining justified alignment. It looks great with two divs using col-lg6- in Bootstrap, but when I switch to col-md-6 or col-sm-6, there are excessive spaces between words to keep t ...