Jansen
Jansen

Reputation: 33

custom text position on ipywidgets button

I am trying to put a "+" sign on a button that reaches all the edges. This is a minimal example, from a Jupyter notebook, first a style:

%%html
<style>
.button_style{
    font-size:155px;
    color: black;
}
</style>

and the button itself:

import ipywidgets as ipyw
button = ipyw.Button(description='+', style={'button_color':'blue'},    
                     layout=ipyw.Layout(width='80px', height='80px'))
button.add_class("button_style")

As you can see, what I tried was making the font size big enough to reach the button edges. But the problem is that the text is not aligned with the middle of the button:

enter image description here

I've played with options like text-align, left-padding, left-margin etc, but they all affect the entire button, i.e. they translate or deform the entire blue square, rather than just the text within it.

Is there any way to do this? Ideally I'd be able to change the center of the cross but always have it reach all edges, and without making the cross itself super fat. But less than ideal solutions are also welcome.

Update:

So the result I am looking for is this:

enter image description here

where the center and ideally also the thickness of the lines can be configured. It doesn't matter if the result is achieved with a '+', as long as the button looks like this and the background color can still be changed with style={'button_color': ..}.

Upvotes: 3

Views: 1009

Answers (2)

Thatkookooguy
Thatkookooguy

Reputation: 7012

As @johannchopin mentioned, this can be done with pseudo-elements. I suggest a solution similar to his but without the inner .custom-plus div. It's better because it will allow you to use the ipywidgets as-is and just add the styling.

This will allow you to use the button from ipywidgets like this:

Style

%%html
<style>
.button_style {
  --size: 80px;
  --line-color: black;
  --line-color-horizontal: var(--line-color);
  --line-color-vertical: var(--line-color);
  --line-stroke: calc(0.125 * var(--size));
  --line-stroke-horizontal: var(--line-stroke);
  --line-stroke-vertical: var(--line-stroke);
  --line-distance: calc(0.2 * var(--size));
  --line-distance-right: var(--line-distance);
  --line-distance-bottom: var(--line-distance);
  --line-hover: lightblue;
  --background: blue;
  --background-hover: var(--background);
  color: black;
  padding: 0;
  background: var(--background);
  width: var(--size);
  height: var(--size);
  position: relative;
  border: none;
  cursor: pointer;
}

.button_style:hover {
  background: var(--background-hover);
}

.button_style:hover::before, .button_style:hover::after {
  background: var(--line-hover);
}

.button_style::before, .button_style::after {
  position: absolute;
  content: "";
  transition: background 250ms;
}

.button_style::before {
  left: 0;
  bottom: var(--line-distance-bottom);
  width: 100%;
  height: var(--line-stroke-horizontal);
  background: var(--line-color-horizontal);
}

.button_style::after {
  right: var(--line-distance-right);
  top: 0;
  height: 100%;
  width: var(--line-stroke-vertical);
  background: var(--line-color-vertical);
}
</style>

Definition

import ipywidgets as ipyw
button = ipyw.Button(description='+', style={'--size':'80px', '--background': 'blue' })
button.add_class("button_style")

You could probably also remove the layout option to define the size of the button since it's optional and we already set the size using CSS variables (--size). Also, using the CSS variables we can set the background color or even change colors on hover (see my snippet for an example).

.button_style {
  --size: 80px;
  --line-color: black;
  --line-color-horizontal: var(--line-color);
  --line-color-vertical: var(--line-color);
  --line-stroke: calc(0.125 * var(--size));
  --line-stroke-horizontal: var(--line-stroke);
  --line-stroke-vertical: var(--line-stroke);
  --line-distance: calc(0.2 * var(--size));
  --line-distance-right: var(--line-distance);
  --line-distance-bottom: var(--line-distance);
  --line-hover: lightblue;
  --background: blue;
  --background-hover: var(--background);
  color: black;
  padding: 0;
  background: var(--background);
  width: var(--size);
  height: var(--size);
  position: relative;
  border: none;
  cursor: pointer;
}

.button_style:hover {
  background: var(--background-hover);
}

.button_style:hover::before,
.button_style:hover::after {
  background: var(--line-hover);
}

.button_style::before,
.button_style::after {
  position: absolute;
  content: "";
  transition: background 250ms;
}

.button_style::before {
  left: 0;
  bottom: var(--line-distance-bottom);
  width: 100%;
  height: var(--line-stroke-horizontal);
  background: var(--line-color-horizontal);
}

.button_style::after {
  right: var(--line-distance-right);
  top: 0;
  height: 100%;
  width: var(--line-stroke-vertical);
  background: var(--line-color-vertical);
}
<button class="button_style"></button>

<button class="button_style" style="--line-distance: 35px; --background: purple; --line-hover: white"></button>

<button class="button_style" style="--line-distance-bottom: 10px; --line-distance-right: 65px; --background: hsl(348, 100%, 61%); --line-color: hsl(48, 100%, 67%); --line-hover: white"></button>

<button class="button_style" style="--line-distance-bottom: 20px; --line-distance-right: 20px; --background: orange; --line-stroke-horizontal: 25px; --line-hover: orange; --background-hover: black"></button>

<div style="margin: 1em 0">
  <button class="button_style" style="--size: 40px"></button>
</div>

Upvotes: 6

johannchopin
johannchopin

Reputation: 14844

I would recommend you to create these 2 bars by using ::before and ::after elements in pure css:

.button_style::before {
  position: absolute;
  left: 0;
  bottom: 15px;
  content: "";
  width: 100%;
  height: 10px;
  background: black;
}

.button_style::after {
  position: absolute;
  top: 0;
  right: 15px;
  content: "";
  height: 100%;
  width: 10px;
  background: black;
}

The final result look like this:

.button_style {
  position: relative;
  font-size: 155px;
  color: black;
  line-height: 0;
  padding: 0;
  background: blue;
  width: 80px;
  height: 80px;
}

.button_style::before {
  position: absolute;
  left: 0;
  bottom: 15px;
  content: "";
  width: 100%;
  height: 10px;
  background: black;
}

.button_style::after {
  position: absolute;
  top: 0;
  right: 15px;
  content: "";
  height: 100%;
  width: 10px;
  background: black;
}
<button class="button_style"></button>

Have a look at the Jsfiddle.

Upvotes: 3

Related Questions