Dragula拖拽Bootstrap网格布局异常:col-md-3与col-md-9排版修正需求
Hey there! Let's figure out how to fix this Bootstrap grid layout issue after using Dragula for dragging.
The core problem here is Bootstrap's 12-column float-based grid system. When you have col-md-3 + col-md-9 + col-md-3 in the same row, the total columns add up to 15—way over the 12-column limit. In your initial order (col-md-9 + col-md-3 + col-md-3), the tall col-md-9 lets the two smaller columns sit side-by-side on the right. But when you reverse the order, col-md-3 + col-md-9 fills the entire 12 columns, so the third col-md-3 gets pushed to the next row.
Here are two solid solutions to get the layout you want:
Rewrite the parent container's layout using Flexbox to bypass Bootstrap's float limitations while keeping drag functionality intact:
/* Convert the column container to Flexbox */ .row.inview.dragula .col-md-12 { display: flex; flex-wrap: wrap; align-items: flex-start; } /* Preserve Bootstrap's column width ratios in Flex */ .row.inview.dragula .col-md-3 { flex: 0 0 25%; /* Matches col-md-3's 25% width (3/12) */ max-width: 25%; } .row.inview.dragula .col-md-9 { flex: 0 0 75%; /* Matches col-md-9's 75% width (9/12) */ max-width: 75%; } /* Key fix: Position the third col-md-3 next to the first one */ .row.inview.dragula .col-md-12 .col-md-3:nth-child(3) { margin-left: -75%; /* Offset by the width of col-md-9 */ margin-top: 243px; /* Match the height of your .box in col-md-3 */ }
Notes:
- Adjust
margin-topto match the actual height of your.boxelements (243px in your code). If heights are dynamic, you can calculate this with jQuery. - Add responsive breakpoints (like
@media (max-width: 768px)) to reset these styles for mobile views, keeping Bootstrap's default behavior on smaller screens.
Use Dragula's drop event to detect the column order and rearrange elements dynamically, keeping each column independently draggable:
// Initialize Dragula (target the inner col-md-12 container) const drake = dragula([document.querySelector('.row.inview.dragula .col-md-12')], { handle: '.handle' // Use your existing drag handle class }); // Listen for the end of a drag-and-drop action drake.on('drop', (el, target) => { const $container = $(target); const $cols = $container.children('.col-md-3, .col-md-9'); // Check if we have the problematic order: col-md-3 → col-md-9 → col-md-3 if ($cols.eq(0).hasClass('col-md-3') && $cols.eq(1).hasClass('col-md-9') && $cols.eq(2).hasClass('col-md-3')) { // Create a wrapper to hold the two side-by-side col-md-3 elements const $leftWrapper = $('<div class="col-md-3 left-wrapper clearfix"></div>'); // Move the first and third columns into the wrapper $cols.eq(0).appendTo($leftWrapper); $cols.eq(2).appendTo($leftWrapper); // Replace the original three columns with the wrapper and col-md-9 $cols.eq(0).remove(); $cols.eq(2).remove(); $container.prepend($leftWrapper); } else { // Reset to original structure if the order changes back $container.find('.left-wrapper').each(function() { $(this).children().insertBefore($(this)); $(this).remove(); }); } });
Add this CSS to style the wrapper:
.left-wrapper { display: flex; flex-direction: column; gap: 15px; /* Match Bootstrap's default gutter spacing */ }
Advantages:
- Fully preserves independent dragging functionality—users won't notice the DOM rearrangement.
- Automatically adapts to any drag order, switching layouts on the fly.
Testing Tips:
- Start with Solution 1 if you want a lightweight, static fix.
- Use Solution 2 if you need dynamic height support or more flexibility with drag orders.
- Always test responsive behavior to ensure layouts work across all screen sizes.
内容的提问来源于stack exchange,提问作者Kris Jon Manait

