twbs / bootstrap

The most popular HTML, CSS, and JavaScript framework for developing responsive, mobile first projects on the web.
https://getbootstrap.com
MIT License
170.25k stars 78.77k forks source link

Responsive Border Utilities #23892

Closed LarryAzevedo closed 7 years ago

LarryAzevedo commented 7 years ago

It would be great to be able to do something like this: <div class="border-top border-lg-top-0 border-lg-left">...</div> So in this example, you'll have:

  1. a 1px top border from xs to md
  2. a 1px left border from lg to xl (the top border get's removed)

Here's what the SASS might look like:

`@each $breakpoint in map-keys($grid-breakpoints) { @include media-breakpoint-up($breakpoint) { $infix: breakpoint-infix($breakpoint, $grid-breakpoints);

    .border#{$infix}-top-0{     border-top: 0 !important;}
    .border#{$infix}-right-0{   border-right: 0 !important;}
    .border#{$infix}-bottom-0{  border-bottom: 0 !important;}
    .border#{$infix}-left-0{    border-left: 0 !important;}
    .border#{$infix}-top{       border-top: 1px solid $gray-200 !important;}
    .border#{$infix}-right{     border-right: 1px solid $gray-200 !important;}
    .border#{$infix}-bottom{    border-bottom: 1px solid $gray-200 !important;}
    .border#{$infix}-left{      border-left: 1px solid $gray-200 !important;}
    .border#{$infix}-x{         border-left: 1px solid $gray-200 !important; border-right: 1px solid $gray-200 !important;}
    .border#{$infix}-y{         border-top: 1px solid $gray-200 !important; border-bottom: 1px solid $gray-200 !important;}
}

}`

mdo commented 7 years ago

No plans to make these responsive.

tmorehouse commented 6 years ago

Too bad, as I have a use case for adding/removing borders based on responsive positioning.

spaceemotion commented 6 years ago

Since I had the same issue today, here's an updated version of @LarryAzevedo's proposal that uses the proper BS4 variables:

@each $breakpoint in map-keys($grid-breakpoints) {
  @include media-breakpoint-up($breakpoint) {
    $infix: breakpoint-infix($breakpoint, $grid-breakpoints);

    .border#{$infix}-top {      border-top: $border-width solid $border-color !important; }
    .border#{$infix}-right {    border-right: $border-width solid $border-color !important; }
    .border#{$infix}-bottom {   border-bottom: $border-width solid $border-color !important; }
    .border#{$infix}-left {     border-left: $border-width solid $border-color !important; }

    .border#{$infix}-top-0 {    border-top: 0 !important; }
    .border#{$infix}-right-0 {  border-right: 0 !important; }
    .border#{$infix}-bottom-0 { border-bottom: 0 !important; }
    .border#{$infix}-left-0 {   border-left: 0 !important; }

    .border#{$infix}-x {
      border-left: $border-width solid $border-color !important;
      border-right: $border-width solid $border-color !important;
    }

    .border#{$infix}-y {
      border-top: $border-width solid $border-color !important;
      border-bottom: $border-width solid $border-color !important;
    }
  }
}
drupalr commented 6 years ago

@spaceemotion Top notch!

ianryde commented 6 years ago

10/10 - used spaceemotions solution here. Quick solution on the back of bootstrap without having to write custom sass.

chrisdavies71 commented 6 years ago

@spaceemotion Which file did you put this code in?

spaceemotion commented 6 years ago

@chrisdavies71 I have an scss file called "_bootstrap.scss" that imports the individual bootstrap files one by one, commenting out the ones i/we don't need.

Directly after the utility import I added the custom changes, so it looks something like this:

@import "~bootstrap/scss/close";
// @import "~bootstrap/scss/modal";
// @import "~bootstrap/scss/tooltip";
// @import "~bootstrap/scss/popover";
// @import "~bootstrap/scss/carousel";
@import "~bootstrap/scss/utilities";
@import 'border-utilities';         // <--- custom file
@import "~bootstrap/scss/print";
DamiansDesign commented 6 years ago

@spaceemotion Thanks for your efforts! Are border colors like border-primary working for you?

For me, if I use border-primary border-md-bottom the border color is reset to default border color (gray).

spaceemotion commented 6 years ago

@DamiansDesign sorry for the late response, I've been quite busy lately.

It's a bit more complicated, but you could do the following:

  1. Extract your bootstrap utilities import to a local file like _utilities.scss:
@import "utilities/align";
@import "utilities/background";
@import "utilities/borders"; <-- replace this with your _border-utilities.scss file
@import "utilities/clearfix";
@import "utilities/display";
@import "utilities/embed";
@import "utilities/flex";
@import "utilities/float";
@import "utilities/position";
@import "utilities/screenreaders";
@import "utilities/shadows";
@import "utilities/sizing";
@import "utilities/spacing";
@import "utilities/text";
@import "utilities/visibility";
  1. Copy the bootstrap border utilities into your own utilities file. My previous addition should go between the .border-left-0 declaration and the @each $color, $value in $theme-colors { call:

https://gist.github.com/spaceemotion/0f750c975fbe9ddf49dc9ab6e69bbfeb

You're losing changes done by updating bootstrap, but you'd just need toupdate your local copy which hopefully is not too much of a hassle.

Hope this helps!

DamiansDesign commented 6 years ago

@spaceemotion thank you for your reply, and I completely understand --I too have been quite busy lately. Thanks for taking the time to reply.

I managed to figure out a solution that didn't require modifying any core files. The solution was to remove the !important declaration.

Like so:

@each $breakpoint in map-keys($grid-breakpoints) {
  @include media-breakpoint-up($breakpoint) {
    $infix: breakpoint-infix($breakpoint, $grid-breakpoints);

    .border#{$infix}-top {      border-top: $border-width solid $border-color ; }
    .border#{$infix}-right {    border-right: $border-width solid $border-color ; }
    .border#{$infix}-bottom {   border-bottom: $border-width solid $border-color ; }
    .border#{$infix}-left {     border-left: $border-width solid $border-color ; }

    .border#{$infix}-top-0 {    border-top: 0 !important; }
    .border#{$infix}-right-0 {  border-right: 0 !important; }
    .border#{$infix}-bottom-0 { border-bottom: 0 !important; }
    .border#{$infix}-left-0 {   border-left: 0 !important; }

    .border#{$infix}-x {
      border-left: $border-width solid $border-color ;
      border-right: $border-width solid $border-color ;
    }

    .border#{$infix}-y {
      border-top: $border-width solid $border-color ;
      border-bottom: $border-width solid $border-color ;
    }
  }
}
davidrhoderick commented 4 years ago

Amazing job @spaceemotion and @DamiansDesign, this is a total keeper! Along with @madmax solution for responsive widths, these should definitely be a part of core.

For responsive design, nearly 100% of the time, adjacent columns need to be made full-width on mobile and if there is a border between them on larger screen sizes, it needs to be removed or moved to between the columns or rows. Along with responsive widths, this is another piece of Bootstrap I find missing that would complete the UI toolkit.

niftylettuce commented 4 years ago

@DamiansDesign and @spaceemotion you are missing this line from your snippet .border#{$infix} { border: $border-width solid $border-color; }

frederikhors commented 4 years ago

@mdo, given the sequel that has had this issue in the community, is there the possibility of having this feature in 5?

abrambailey commented 4 years ago

Also think this is a natural fit for bs 5.

tacomanator commented 4 years ago

Nice to have. I found a need for this feature when using a border between two items displayed as flex column on small screens or as a flex row on large screens, which requires changing the border from top/bottom to left/right.

ozgurg commented 2 years ago

In Bootstrap 5, you can add "responsive: true" for utility that you want to make responsive.

"border-top": (
  responsive: true, /* Add this */
  property: border-top,
  values: (
    null: $border-width solid $border-color,
    0: 0,
  )
),

And when you compile, following classes will be generated:

.border-top
.border-top-0
.border-top-sm
.border-top-sm-0
.border-top-md
.border-top-md-0
.border-top-lg
.border-top-lg-0
.border-top-xl
.border-top-xl-0
.border-top-xxl
.border-top-xxl-0

See for detailed instruction: https://getbootstrap.com/docs/5.1/utilities/api/#enable-responsive

fulldecent commented 2 years ago

For people that want to use baseline Bootstrap and you don't compile (bonus points if you are using CDN!) here is a simple workaround:

        <p class="d-none d-lg-block col-lg-4 border-start border-5">
{% for tag in page.tags %}
          <a href="/posts-by-tag#{{ tag | slugify }}">#{{ tag }}</a>
{% endfor %}  
        </p>
        <p class="d-block d-lg-none">
{% for tag in page.tags %}
          <a href="/posts-by-tag#{{ tag | slugify }}">#{{ tag }}</a>
{% endfor %}  
        </p>

I want to show something on the right with a border if there is enough width and otherwise show it below without border.

Basically I'm adding a border between the columns for this aside.

Natshah commented 2 years ago

Bootstrap Borders Utilities https://www.npmjs.com/package/bootstrap-borders-utilities

npm i bootstrap-borders-utilities

huwiler commented 1 year ago

For those of us forced to work within the constraints of baseline bootstrap who also don't want to resort to redundant markup based solutions, here's a javascript workaround. This example works as if a compiled border-start-md were applied to an element with id "preview".

(() => {
    const mdMediaQuery = window.matchMedia('(min-width: 768px)'); // twbs *-md
    mdMediaQuery.addEventListener('change', e => {
        e.target.matches ?
            document.getElementById('preview').classList.add('border-start') :
            document.getElementById('preview').classList.remove('border-start');
    });
    const changeEvent = new Event('change');
    mdMediaQuery.dispatchEvent(changeEvent);
})();
joho1968 commented 6 months ago

I fail to grasp why these wouldn't/shouldn't be responsive out of the box. Having two "containers" side by side, it may make sense to have a border-start on the rightmost container, when the design "collapses" so that the right container is now placed under the left container, the border should be removed, or that's what I'd want anyway. Very strange IMHO ... :thinking: