JSFiddle - React, Tailwind, and code Playground
by AsciiSmoke
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Draggable and Resizable Grid</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div id="grid-container">
<div class="grid-item player" draggable="true">Player</div>
<div class="grid-item interaction" draggable="true">Interaction</div>
<div class="grid-item about" draggable="true">About</div>
</div>
<script src="script.js"></script>
</body>
</html>
CSS
#grid-container {
display: grid;
grid-template-columns: repeat(6, minmax(150px, 1fr)); /* Each column is at least 150px wide */
grid-template-rows: repeat(8, minmax(100px, 1fr)); /* Each row is at least 100px tall */
gap: 10px;
width: 100%;
height: 100vh; /* Make the grid fill the viewport */
position: relative; /* Required for absolute positioning */
border: 1px solid #ccc;
}
.grid-item {
background-color: #eee;
border: 1px solid #999;
display: flex;
justify-content: center;
align-items: center;
cursor: move;
resize: both; /* Make items resizable */
overflow: auto; /* Ensure resizable works */
position: absolute; /* Use absolute positioning to move items within the grid */
}
/* Optional styling for visual appeal */
.grid-item.player {
background-color: lightblue;
}
.grid-item.interaction {
background-color: lightgreen;
}
.grid-item.about {
background-color: lightcoral;
}
JavaScript
// Draggable and resizable implementation
let draggedElement = null;
let gridContainer = document.getElementById('grid-container');
// Function to snap the element to the grid
function snapToGrid(element) {
const gridCellWidth = gridContainer.offsetWidth / 6;
const gridCellHeight = gridContainer.offsetHeight / 8;
let top = parseFloat(element.style.top);
let left = parseFloat(element.style.left);
// Calculate the nearest grid position
const snappedTop = Math.round(top / gridCellHeight) * gridCellHeight;
const snappedLeft = Math.round(left / gridCellWidth) * gridCellWidth;
// Snap the element to the grid
element.style.top = `${snappedTop}px`;
element.style.left = `${snappedLeft}px`;
}
// Event listeners for dragging
document.querySelectorAll('.grid-item').forEach(item => {
item.addEventListener('dragstart', function (event) {
draggedElement = event.target;
draggedElement.style.zIndex = 1000; // Bring the dragged element to front
});
item.addEventListener('dragend', function (event) {
draggedElement.style.zIndex = ''; // Reset z-index after dragging
snapToGrid(draggedElement); // Snap the element to the grid
checkForOverlap(); // Ensure no overlap
});
// Enable resizing the elements up to the grid constraints
item.addEventListener('resize', function () {
let maxWidth = gridContainer.offsetWidth;
let maxHeight = gridContainer.offsetHeight;
// Constrain the resize to 6 columns and 8 rows
const gridCellWidth = maxWidth / 6;
const gridCellHeight = maxHeight / 8;
const width = Math.min(this.offsetWidth, gridCellWidth * 6); // Max 6 columns wide
const height = Math.min(this.offsetHeight, gridCellHeight * 8); // Max 8 rows tall
this.style.width = `${width}px`;
this.style.height = `${height}px`;
});
});
// Function to check for overlap and adjust positions
function...