CSS draw circle inside circle, as display table-cell - css

I am trying to draw a solid circle inside a ring. I got the outer circle working great, but the inner one is filling up the entire circle whereas I want a few pixels inner padding.
I thought this would be simple but because I am using display:table for the container and table-cell for the inner bits padding/margin aren't behaving as I'd hope.
Example jsfiddle, https://jsfiddle.net/joshuaohana/5ewemw0q/ in this I'd like to have the red inner bit not take up the entire circle but have a few pixels spacing between it and the outer border.
The reason it's all table/table-cell is to easily manage vertically aligning the circle with its associated label.
<div class="radio">
<label>label</label>
</div>
.radio {
display: table;
border-spacing: 10px;
margin: 0 -10px;
}
.radio:before {
display: table-cell;
vertical-align: middle;
height: 20px;
width: 20px;
border: 2px solid blue;
border-radius: 50%;
content: "";
background-color: red;
}
.radio > label {
display: table-cell;
vertical-align: middle;
}
How can I get the inner circle to have some inner padding? Tried margin, padding, border-spacing, etc... all to no avail.

I solved by making the parent relative and absolutely positioning the children, with the inner bits done by an :after pseudo element. Working great now
https://jsfiddle.net/joshuaohana/5ewemw0q/2/
.radio {
display: table;
border-spacing: 10px;
margin: 0 -10px;
position: relative;
}
.radio:before {
display: table-cell;
vertical-align: middle;
height: 20px;
width: 20px;
border: 2px solid blue;
border-radius: 50%;
content: "";
position: absolute;
}
.radio:after {
display: table-cell;
vertical-align: middle;
height: 10px;
width: 10px;
background: red;
border-radius: 50%;
content: "";
position: absolute;
left: 16.5px;
top: 16.5px;
}
.radio > label {
display: table-cell;
vertical-align: middle;
position: absolute;
left: 42px;
top: 12px;
}

You could add a third color if you add a inset to box-shadow css.
box-shadow: inset 0px 0px 10px 1px yellow;
https://jsfiddle.net/wallyglenn/j3e78n4p/

Related

CSS paragraph layout with a border, and ::before element that needs its own border

I've got some text that needs the following:
border around the text
a ::before element that has its own border and background color
Basically, I want it to look like this:
So far, I've got this:
My CSS:
.caution {
border: 0.5pt solid black;
padding-left: 3pt;
padding-right: 3pt;
display: table;
}
.caution::before {
display: table-cell;
border: 0.5pt solid black;
background-color: #deddde;
text-align: center;
content: "caution";
}
My html:
<p class="caution">Caution text</p>
The result is that the ::before box is nested inside the .caution box, instead of overlapping. The gaps on the left and right are caused by the padding-left and padding-right statements.
I've also tried this without the display:table, that didn't help. I need the padding-left and padding-right to apply to the text (to ensure the text doesn't come right up to the border), but not to the ::before element. There's no selector that allows me to apply properties to 'all of .caution except the ::before element'.
How can I get the borders to behave the way I want them to?
You can try this - it's not perfect, but it's a start :)
.caution {
border: 0.5pt solid black;
display: inline-block;
max-width: 200px;
padding: 10px;
}
.caution::before {
display: block;
border-bottom: 0.5pt solid black;
margin: -10px;
margin-bottom: 10px;
background-color: #deddde;
text-align: center;
content: "Caution";
}
It will render the following:
Setting only border-bottom (as in answer by Yogendra Chauhan, though I only noticed that afterwards) can help:
.caution {
border: 0.5pt solid black;
padding-left: 3pt;
padding-right: 3pt;
display: block;
}
.caution::before {
border-bottom: 0.5pt solid black;
background-color: #deddde;
text-align: center;
content: "caution";
display: block;
margin: 0 -3pt;
}
However, you might see a small white line at the ends of the bottom border when you zoom to 6,400% in your PDF viewer.
Here is the working example:
.caution {
position: relative;
border: 1px solid #000000;
height: 200px;
width: 300px;
padding-left: 5px;
padding-right: 5px;
padding-top: 30px;
}
.caution::before {
position: absolute;
background-color: #deddde;
text-align: center;
content: "caution";
text-transform: capitalize;
display: block;
width: 100%;
border-bottom: 1px solid #000000;
top: 0;
left: 0;
line-height: 25px;
}
<div class="caution">Caution text</div>

How to center text inside :before pseudo element?

I have code like this:
span {
border-radius: 50%;
background-color: #d8d9dd;
border: 6px solid #262c40;
width: 25px;
height: 25px;
margin: 30px 0 0 40px;
display: block;
}
span:before {
content: attr(data-value);
position: relative;
white-space: pre;
display: inline;
top: -27px;
left: -29px;
width: 200px;
text-align: center;
}
<span data-value="November 2016"></span>
<span data-value="May 2016"></span>
How can I center the text inside :before pseudo element to be in the middle of the span? Is it possible?
The best thing would be to position the before pseudo element absolutely with respect to the span using the popular centering technique:
top: 0;
left: 50%;
transform: translate(-50%, -25px);
Note that -25px is to offset the text above the circles (which has height 25px) - see demo below:
span {
border-radius: 50%;
background-color: #d8d9dd;
border: 6px solid #262c40;
width: 25px;
height: 25px;
margin: 30px 0 0 40px;
display: block;
position:relative;
}
span:before {
content: attr(data-value);
position: absolute;
white-space: pre;
display: inline;
top: 0;
left: 50%;
transform: translate(-50%, -25px);
}
<span data-value="November 2016"></span>
<span data-value="May 2016"></span>
Source
From MDN:
[the :before pseudo-element] is inline by default
Giving inline elements a width does nothing, so you need to style it as display: block (or inline-block if that is more appropriate). It also turns out that you need to adjust the left value to approximately -88px to get the text centred over the circle.
span {
border-radius: 50%;
background-color: #d8d9dd;
border: 6px solid #262c40;
width: 25px;
height: 25px;
margin: 30px 0 0 40px;
display: block;
}
span:before {
content: attr(data-value);
position: relative;
white-space: pre;
display: inline;
top: -27px;
left: -88px;
width: 200px;
text-align: center;
display: block;
}
<span data-value="November 2016"></span>
<span data-value="May 2016"></span>
I recommend against using negative translations. It might end up outside the viewport if you don't do it enough carefully.
Moreover, you shouldn't insert contents with pseudo-elements. Pseudo-elements should only be used for styling purposes. Like this:
body {
display: inline-block;
}
span {
display: block;
text-align: center;
}
span:after {
content: '';
border-radius: 50%;
background-color: #d8d9dd;
border: 6px solid #262c40;
width: 25px;
height: 25px;
margin: 10px auto 30px;
display: block;
}
<span>November 2016</span>
<span>May 2016</span>
The text inside the span is centered due to text-align: center.
The pseudo-element circle is centered due to margin-left: auto and margin-right: auto.
We should use LOGICAL CODE and not any hit and trail and playing around with numbers!
I used flex in the pseudo element to center it first upon the span element.
Then i used transform to Logically position the pseudo element.
/*styling to just make the presentation look good*/
body{
border:5px solid black;
padding:50px;
display:flex;
flex-direction: column;
justify-content:center;
align-items:center;
}
/* main stylings start here*/
span {
border-radius: 50%;
background-color: #d8d9dd;
border: 6px solid #262c40;
width: 25px;
height: 25px;
margin: 30px 0 0 40px;
display: block;
}
span:before {
content: attr(data-value);
width:150px;
border:solid black 1px;
/*use flex to center it to middle & upon the span*/
display:flex;
justify-content:center;
align-items:center;
/*use transform and position it LOGICALLY (by considering border widths of the parent span and ofcourse using calc() )*/
transform: translate(calc(-50% + 2 * 6px), calc(-100% - 6px));
}
<span data-value="November 2016"></span>
<span data-value="May 2016"></span>
I would request to use LOGICAL Code rather than design-breaking hit and trail values.
Write Responsive Code. Happy Coding!
I was beaten to this, but here is my solution:
span {
border-radius: 50%;
background-color: #d8d9dd;
border: 6px solid #262c40;
width: 25px;
height: 25px;
margin: 30px 0 0 40px;
display: block;
}
span:before {
content: attr(data-value);
position: relative;
white-space: pre;
display: inline-block;
top: -27px;
left: -50px;
width: 125px;
text-align: center;
}
The changes are to use inline-block display on the :before style and to adjust the left and width of the text.
Add display:inline-block; and add margin-left:-87px. where 87px derived from
100px(50% of whole width 200px)-13px(50% of span width 25px)
span {
border-radius: 50%;
background-color: #d8d9dd;
border: 6px solid #262c40;
width: 25px;
height: 25px;
margin: 30px 0 0 40px;
display: block;
}
span:before {
content: attr(data-value);
position: relative;
white-space: pre;
display: inline-block;
top: -27px;/*
left: -29px;*/
margin-left: -87px;
width: 200px;
text-align: center;
}
<span data-value="November 2016"></span>
<span data-value="May 2016"></span>

Vertical align :after element

I've tried the various responses here but no luck.
I need to vertical align an after element:
content: "";
width: 30px;
height: 15px;
background: transparent url('/img/test.png') no-repeat;
float: right;
border: 1px solid red;
This does not work:
vertical-align: middle;
Nor does:
vertical-align: -50%;
From those answers linked to, the vertical-align:inherit; on the element worked for me when I set the parent element to vertical-align:top;, nothing else seemed to work for me.
You can use line-height on the parent element and display:inline-block on the pseudo :after
.box {
width: 100px;
height: 100px;
background: #CCC;
line-height: 100px;
text-align: center;
}
.box:after {
content: "";
width: 30px;
height: 15px;
background: transparent;
border: 1px solid red;
display: inline-block;
}
DEMO: https://jsfiddle.net/tianes/zhwL3rrq/

Inner border that does not push contents

I'm trying to fill an element with multiple colors using CSS. Currently, I have this CSS:
div.container {
width: 100px;
border: 1px dotted;
font-size: 10px;
}
.box {
box-sizing:border-box;
display: inline-block;
width: 12px;
height: 12px;
border-radius: 50%;
border: 6px solid #99FF99;
border-bottom-color: #FF9966;
border-right-color: #FF9966;
}
fiddle
Problem is that the contents are not over the border, so it looks like this:
How can I get the contents of span class="box" to stay in the middle of the element (i.e. over the colored circle)?
How about using absolute and relative positions, and making the circle as a pseudo element.
DEMO: http://jsfiddle.net/d0cv4bc8/8/
div.container {
width: 100px;
border: 1px dotted;
font-size: 12px;
}
.box {
position: relative;
}
.box::before {
content: "";
box-sizing:border-box;
display: inline-block;
width: 12px;
height: 12px;
border-radius: 50%;
border: 6px solid #99FF99;
border-bottom-color: #FF9966;
border-right-color: #FF9966;
position: absolute;
z-index: -1;
}
Only way I can get the contents centered vertically and horizontally is to put contents inside a span, moved left and up by half of box's border width.
http://jsfiddle.net/d0cv4bc8/11/
CSS
.box .contents {
display:inline-block;
position: relative;
left: -3px;
top: -3px;
}
HTML
<div class="container">
<span class="box"><span class="contents">1</span></span>
</div>

Make child div text content NOT expand its parent fixed-positioned div's width

I am working on kind of a popup. Its structure is very simple and is as follows:
<div class = "popup">
<div class = "upper">
<img src = "http://www.tapeta-mis-galazki-koala.na-pulpit.com/pokaz_obrazek.php?adres=mis-galazki-koala&rozdzielczosc=128x128" />
</div>
<div class = "description">This is a very interesting description of what you can see above.</div>
</div>
with styles of
.popup
{
position: fixed;
left: 50px;
top: 50px;
border: 1px solid;
background: #fff;
padding: 10px;
box-shadow: 0 0 5px #000;
}
.popup .upper {
min-width: 100px;
min-height: 100px;
border: 1px solid;
padding: 5px;
display: inline-block;
}
.popup .upper img {
display: block;
}
and here is a fiddle with the code applied.
As you can see, the div.popup is positioned as fixed to the body.
What I want to achieve is to make the div.description NOT extend its parent div.popup width when it contains much text, instead it should wrap the text to be multilined and be of width of the div.popup. The div.popup width should be determined by the div.upper width and its content. In other words I mean to have div.description's width AT MOST of the div.upper's width, regardless to its (div.description text content).
EDIT
There's this little difficulty: the image content is not static and may be dynamically changed so the width is not constant.
Is that even possible to achieve that with CSS?
http://jsfiddle.net/de6fr/1/ - a basic example of how to fix
You're basically using popup as a container, which means that if you want to retain its width, that's what you have to work on. I used the max-width property with .popup like this:
.popup {
position: fixed;
left: 50px;
top: 50px;
border: 1px solid;
background: #fff;
padding: 10px;
box-shadow: 0 0 5px #000;
display: table;
width: 1px;
}
.popup > div {
display: table-row;
}
.popup .upper {
min-width: 100px;
min-height: 100px;
border: 1px solid;
padding: 5px;
}
.popup .upper img {
display: block;
}
Update - Flexible
http://jsfiddle.net/de6fr/4/
The fix for making it flexible is to use a CSS hack, which basically changes the nature of the element to a table
The nature of CSS (cascading style sheets) means that it's pretty hard to get a parent DIV to take the size of a child div without some crazy ideas involved. However, there's nothing preventing a "table" with a really small width doing that, as per this code:
.popup
{
position: fixed;
left: 50px;
top: 50px;
border: 1px solid;
background: #fff;
padding: 10px;
box-shadow: 0 0 5px #000;
display: table;
width: 1px;
}
.popup .upper {
min-width: 100px;
min-height: 100px;
border: 1px solid;
padding: 5px;
display: table-row;
}
.popup .upper img {
display: block;
}
.popup .description {
display: table-row;
}
You have not defined the width for fixed element so add some width to your fiexed element
.popup
{
position: fixed;
left: 50px;
top: 50px;
border: 1px solid;
background: #fff;
padding: 10px;
box-shadow: 0 0 5px #000;
width: 100%;
}
here is the demo
Add a CSS property to your popup class and Give it a width
.popup
{
position: fixed;
left: 50px;
top: 50px;
border: 1px solid;
background: #fff;
padding: 10px;
box-shadow: 0 0 5px #000;
overflow:scroll;
width:400px;
}

Resources