61

While I was fiddling with this 'Fancy 3D Button' example, I found that the width seemed to be hard-coded to fit the text's width.

Here is the HTML / CSS:

body {
  background-image: url(http://subtlepatterns.com/patterns/ricepaper.png)
}
a {
  position: relative;
  color: rgba(255, 255, 255, 1);
  text-decoration: none;
  background-color: rgba(219, 87, 5, 1);
  font-family: 'Yanone Kaffeesatz';
  font-weight: 700;
  font-size: 3em;
  display: block;
  padding: 4px;
  -webkit-border-radius: 8px;
  -moz-border-radius: 8px;
  border-radius: 8px;
  -webkit-box-shadow: 0px 9px 0px rgba(219, 31, 5, 1), 0px 9px 25px rgba(0, 0, 0, .7);
  -moz-box-shadow: 0px 9px 0px rgba(219, 31, 5, 1), 0px 9px 25px rgba(0, 0, 0, .7);
  box-shadow: 0px 9px 0px rgba(219, 31, 5, 1), 0px 9px 25px rgba(0, 0, 0, .7);
  margin: 100px auto;
  width: 160px;
  text-align: center;
  -webkit-transition: all .1s ease;
  -moz-transition: all .1s ease;
  -ms-transition: all .1s ease;
  -o-transition: all .1s ease;
  transition: all .1s ease;
}
a:active {
  -webkit-box-shadow: 0px 3px 0px rgba(219, 31, 5, 1), 0px 3px 6px rgba(0, 0, 0, .9);
  -moz-box-shadow: 0px 3px 0px rgba(219, 31, 5, 1), 0px 3px 6px rgba(0, 0, 0, .9);
  box-shadow: 0px 3px 0px rgba(219, 31, 5, 1), 0px 3px 6px rgba(0, 0, 0, .9);
  position: relative;
  top: 6px;
}
<link href='http://fonts.googleapis.com/css?family=Yanone+Kaffeesatz:700' rel='stylesheet' type='text/css'>

<a href="javascript:void(0);">Push me!</a>

Normal look

If I remove the width property, the button would fill the page width.

Without the width property

Is there any way to make the button's width fit to the text, automatically?

misterManSam
  • 24,303
  • 11
  • 69
  • 89
chenaren
  • 2,090
  • 1
  • 19
  • 24

11 Answers11

71

If you are developing to a modern browser. https://caniuse.com/#search=fit%20content

You can use:

width: fit-content;
Roger Cruz
  • 841
  • 6
  • 8
45

Remove the width and display: block and then add display: inline-block to the button. To have it remain centered you can either add text-align: center; on the body or do the same on a newly created container.

The advantage of this approach (as opossed to centering with auto margins) is that the button will remain centered regardless of how much text it has.

Example: http://cssdeck.com/labs/2u4kf6dv

Natsu
  • 2,045
  • 16
  • 11
  • Probably want to use left / right padding as well. Something like `padding: 5px 20px` (`padding: [top/bottom] [left/right]`). There doesn't seem to be a need to change the default `display: inline`. – misterManSam Dec 31 '14 at 15:20
  • @misterManSam: The need is that OP wants to use vertical margin. You can't apply that with a `display: inline` element. – Natsu Dec 31 '14 at 19:03
12

I like Roger Cruz's answer of:

width: fit-content;

and I just want to add that you can use

padding: 0px 10px;

to add a nice 10px padding on the right and left side of the text in the button. Otherwise the text would be right up along the edge of the button and that wouldn't look good.

Matt Wyndham
  • 371
  • 3
  • 6
6

Pretty late and not sure if this was available when the question was asked, set width: auto;

Seems to do the trick

Khristos
  • 973
  • 2
  • 11
  • 22
4

Keeping the element's size relative to its content can also be done with display: inline-flex and display: table

The centering can be done with..

  • text-align: center; on the parent (or above, it's inherited)

  • display: flex; and justify-content: center; on the parent

  • position: absolute; left: 50%; transform: translateX(-50%); on the element with position: relative; (at least) on the parent.

Here's a flexbox guide from CSS Tricks

Here's an article on centering from CSS Tricks.

Keeping an element only as wide as its content..

  • Can use display: table;

  • Or inline-anything including inline-flex as used in my snippet example below.

Keep in mind that when centering with flexbox's justify-content: center; when the text wraps the text will align left. So you will still need text-align: center; if your site is responsive and you expect lines to wrap.

body {
  display: flex;
  flex-direction: column;
  height: 100vh;
  padding: 20px;
}
.container {
  display: flex;
  justify-content: center; /* center horizontally */
  align-items: center; /* center vertically */
  height: 50%;
}
.container.c1 {
  text-align: center; /* needed if the text wraps */
  /* text-align is inherited, it can be put on the parent or the target element */
}
.container.c2 {
 /* without text-align: center; */
}
.button {
  padding: 5px 10px;
  font-size: 30px;
  text-decoration: none;
  color: hsla(0, 0%, 90%, 1);
  background: linear-gradient(hsla(21, 85%, 51%, 1), hsla(21, 85%, 61%, 1));
  border-radius: 10px;
  box-shadow: 2px 2px 15px -5px hsla(0, 0%, 0%, 1);
}
.button:hover {
  background: linear-gradient(hsl(207.5, 84.8%, 51%), hsla(207, 84%, 62%, 1));
  transition: all 0.2s linear;
}
.button.b1 {
    display: inline-flex; /* element only as wide as content */
}
.button.b2 {
    display: table; /* element only as wide as content */
}
<div class="container c1">
  <a class="button b1" href="https://stackoverflow.com/questions/27722872/">This Text Is Centered Before And After Wrap</a>
</div>
<div class="container c2">
  <a class="button b2" href="https://stackoverflow.com/questions/27722872/">This Text Is Centered Only Before Wrap</a>
</div>

Fiddle

https://jsfiddle.net/Hastig/02fbs3pv/

Hastig Zusammenstellen
  • 4,286
  • 3
  • 32
  • 45
2

If you are aiming for maximum browser support, modern approach is to place button in a div with display:flex; and flex-direction:row; The same trick will work for height with flex-direction:column; or both height and width(will require 2 divs)

Aleks
  • 894
  • 10
  • 14
2

This seems to solve the issue:

display: inline-block;
width: auto;
Dave
  • 3,073
  • 7
  • 20
  • 33
  • Welcome to Stack Overflow. Code without any explanation are rarely helpful. Stack Overflow is about learning, not providing snippets to blindly copy and paste. Please edit your question and explain how it answers the specific question being asked. See [How to Answer](https://stackoverflow.com/help/how-to-answer). – Sfili_81 Mar 17 '22 at 15:42
1

Try to add display:inline; to the CSS property of a button.

Mai
  • 363
  • 3
  • 16
1

just add display: inline-block; property and removed width.

krishna
  • 11
  • 4
0

Try add width: 100% for tag button

  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Sep 28 '21 at 06:22
0

I do not see anyone mention about this solution: margin: auto; elements inside a display: flex; parent. Here just add display: flex; to the body:

a {
  position: relative;
  color: rgba(255, 255, 255, 1);
  text-decoration: none;
  background-color: rgba(219, 87, 5, 1);
  font-family: 'Yanone Kaffeesatz';
  font-weight: 700;
  font-size: 3em;
  display: block;
  padding: 4px;
  -webkit-border-radius: 8px;
  -moz-border-radius: 8px;
  border-radius: 8px;
  -webkit-box-shadow: 0px 9px 0px rgba(219, 31, 5, 1), 0px 9px 25px rgba(0, 0, 0, .7);
  -moz-box-shadow: 0px 9px 0px rgba(219, 31, 5, 1), 0px 9px 25px rgba(0, 0, 0, .7);
  box-shadow: 0px 9px 0px rgba(219, 31, 5, 1), 0px 9px 25px rgba(0, 0, 0, .7);
  margin: 100px auto;
  text-align: center;
  -webkit-transition: all .1s ease;
  -moz-transition: all .1s ease;
  -ms-transition: all .1s ease;
  -o-transition: all .1s ease;
  transition: all .1s ease;
}
body {
 display: flex;
}
<body>
    <a href="javascript:void(0);">Push me!</a>
</body>
Vu Viet Hung
  • 180
  • 3
  • 7