tailwindlabs / tailwindcss

A utility-first CSS framework for rapid UI development.
https://tailwindcss.com/
MIT License
83.07k stars 4.21k forks source link

Individual Border Settings #559

Closed bcorcoran closed 6 years ago

bcorcoran commented 6 years ago

Currently it is impossible to use only tailwind to set different border styles or colors per side.

This was exaggerated when I tried to accomplish a CSS triangle, such as: https://css-tricks.com/snippets/css/css-triangle/

I could use an SVG in this particular instance, but that isn't the point. This is a limitation with the way border classes are currently defined.

If possible, I think it would be best if border{-side?}{-width?} were left in tact, but also allowing:

border{-side?}{-style?} border{-side?}{-color?}

spiltcoffee commented 6 years ago

As discussed over in #560 (and previously at tailwindcss/discuss#46), this is probably not something that would be added to Tailwind due to how much data it would add to the default stylesheet.

If you would style like this, you could achieve what you want via a plugin. As an example, see https://github.com/spiltcoffee/tailwindcss/commit/e3f41fb746b1f1388cde2a4bd44f5b4d9f0b0d55

adamwathan commented 6 years ago

Yeah not going to add this at the moment, would be an easy plugin to write though đź‘Ť

jameshahn2 commented 6 years ago

Wow. It must be easy if I pulled it off. For anyone else that Google CSS triangles in TailwindCSS, this is how it's done. Go to tailwind/config/tailwind.js, find the plugins section and drop this code in there:

  plugins: [
    container({
      // center: true,
      // padding: '1rem',
    }),

    function({ addComponents }) {
      const arrows = {
        ".arrow-up": {
          width: "0px",
          height: "0px",
          borderLeft: "5px solid transparent",
          borderRight: "5px solid transparent",
          borderBottom: "5px solid black"
        },

        ".arrow-down": {
          width: "0",
          height: "0",
          borderLeft: "20px solid transparent",
          borderRight: "20px solid transparent",
          borderTop: "20px solid #f00"
        },

        ".arrow-right": {
          width: "0",
          height: "0",
          borderTop: "60px solid transparent",
          borderBottom: "60px solid transparent",
          borderLeft: "60px solid green"
        },

        ".arrow-left": {
          width: "0",
          height: "0",
          borderTop: "10px solid transparent",
          borderBottom: "10px solid transparent",
          borderRight: "10px solid blue"
        }
      };
      addComponents(arrows);
    }
  ],

You just wrote a plugin, congrats!

Use in your Tailwind classes like everything else. For example

<div class='arrow-down'></div>

johnmutuma5 commented 4 years ago

An example for the individual border colors:

plugins:[
    plugin(function({ addUtilities, theme, config }) {
      const themeColors = theme('colors');
      const individualBorderColors = Object.keys(themeColors).map(colorName => ({
        [`.border-b-${colorName}`]: {
          borderBottomColor: themeColors[colorName]
        },
        [`.border-t-${colorName}`]: {
          borderTopColor:  themeColors[colorName]
        },
        [`.border-l-${colorName}`]: {
          borderLeftColor:  themeColors[colorName]
        },
        [`.border-r-${colorName}`]: {
          borderRightColor:  themeColors[colorName]
        }
      }));

      addUtilities(individualBorderColors);
    }),
]
rjworks commented 3 years ago

An example for the individual border colors:

plugins:[
    plugin(function({ addUtilities, theme, config }) {
      const themeColors = theme('colors');
      const individualBorderColors = Object.keys(themeColors).map(colorName => ({
        [`.border-b-${colorName}`]: {
          borderBottomColor: themeColors[colorName]
        },
        [`.border-t-${colorName}`]: {
          borderTopColor:  themeColors[colorName]
        },
        [`.border-l-${colorName}`]: {
          borderLeftColor:  themeColors[colorName]
        },
        [`.border-r-${colorName}`]: {
          borderRightColor:  themeColors[colorName]
        }
      }));

      addUtilities(individualBorderColors);
    }),
]

how to use?

CavalcanteLeo commented 3 years ago

@rjworks use tailwind.config.js

const plugin = require('tailwindcss/plugin')

module.exports = {

 //... all other configs 

  plugins: [
    plugin(function ({ addUtilities, theme, config }) {
      const themeColors = theme('colors')
      const individualBorderColors = Object.keys(themeColors).map(
        (colorName) => ({
          [`.border-b-${colorName}`]: {
            borderBottomColor: themeColors[colorName],
          },
          [`.border-t-${colorName}`]: {
            borderTopColor: themeColors[colorName],
          },
          [`.border-l-${colorName}`]: {
            borderLeftColor: themeColors[colorName],
          },
          [`.border-r-${colorName}`]: {
            borderRightColor: themeColors[colorName],
          },
        })
      )

      addUtilities(individualBorderColors)
    }),
  ],
}
GLaDO8 commented 3 years ago

4404 per-side border colors have now been added!

rjworks commented 3 years ago

Let’s go

eswat2 commented 3 years ago

Awesome, exactly what I was looking for last night to finish my port:

https://wc-sudoku.vercel.com

Just have 4 lines of CSS and one CSS variable that I couldn't get into Tailwind...

R4YM3 commented 3 years ago

4404 doesn't work for me.

I have extended the code of johnmutuma5.

    plugins: [
        plugin(function ({ addUtilities, theme, config }) {
            const themeColors = theme("colors");
            const individualBorderColors = Object.keys(themeColors).map(
                (colorName) => {

                    if (typeof themeColors[colorName] == 'string') {
                        return ({
                            [`.border-b-${colorName}`]: {
                                borderBottomColor: themeColors[colorName],
                            },
                            [`.border-t-${colorName}`]: {
                                borderTopColor: themeColors[colorName],
                            },
                            [`.border-l-${colorName}`]: {
                                borderLeftColor: themeColors[colorName],
                            },
                            [`.border-r-${colorName}`]: {
                                borderRightColor: themeColors[colorName],
                            },
                        })
                    }

                    const colors =  {};

                    Object.keys(themeColors[colorName]).forEach(level => {
                        colors[`.border-b-${colorName}-${level}`] = {
                            borderBottomColor: themeColors[colorName][level]
                        }
                        colors[`.border-t-${colorName}-${level}`] = {
                            borderTopColor: themeColors[colorName][level]
                        }
                        colors[`.border-l-${colorName}-${level}`] = {
                            borderLeftColor: themeColors[colorName][level]
                        }
                        colors[`.border-r-${colorName}-${level}`] = {
                            borderRightColor: themeColors[colorName][level]
                        }
                    });

                    return colors;
                }
            );

            addUtilities(individualBorderColors);
        }),
bcorcoran commented 3 years ago

@RobinMalfait Requesting discussion on this to be closed, as the issue is resolved

ciulic commented 3 years ago

To match the TailwindCSS implementation enabled only for JIT, where the guys have added support with this PR: https://github.com/tailwindlabs/tailwindcss/pull/4404/files I came across with creating a plugin like this:

module.exports = plugin(({ matchUtilities, theme, variants, corePlugins }) => {
  matchUtilities(
    {
      'border-t': (value) => {
        if (!corePlugins('borderOpacity')) {
          return {
            'border-top-color': value,
          };
        }

        return withAlphaVariable({
          color: value,
          property: 'border-top-color',
          variable: '--tw-border-opacity',
        });
      },
      'border-r': (value) => {
        if (!corePlugins('borderOpacity')) {
          return {
            'border-right-color': value,
          };
        }

        return withAlphaVariable({
          color: value,
          property: 'border-right-color',
          variable: '--tw-border-opacity',
        });
      },
      'border-b': (value) => {
        if (!corePlugins('borderOpacity')) {
          return {
            'border-bottom-color': value,
          };
        }

        return withAlphaVariable({
          color: value,
          property: 'border-bottom-color',
          variable: '--tw-border-opacity',
        });
      },
      'border-l': (value) => {
        if (!corePlugins('borderOpacity')) {
          return {
            'border-left-color': value,
          };
        }

        return withAlphaVariable({
          color: value,
          property: 'border-left-color',
          variable: '--tw-border-opacity',
        });
      },
    },
    {
      values: (({ DEFAULT: _, ...colors }) => colors)(
        flattenColorPalette(theme('borderColor')),
      ),
      variants: variants('borderColor'),
      type: 'color',
    },
  );
});