Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a Snowflake shape that contains text in shape

I'm trying to create a snowflake on my webpage for the winter season.

The first thing I tried was creating it with SVG:

enter image description here

<h3>Koch Snowflake Frac</h3>
<svg viewBox="-5 -5 110 110" xmlns="http://www.w3.org/2000/svg">
  <polyline stroke="cornflowerblue" stroke-width="2" fill="rgba(255,255,255,0.5)" points="55 5, 
                    60 10, 
                    65 10, 
                    65 15,
                    70 20,
                    75 20,
                    80 15,
                    85 20,
                    90 20,
                    85 25,
                    90 30,
                    80 30,
                    75 35,
                    80 40,
                    90 40,
                    85 45,
                    90 50,
                    85 50,
                    80 55,
                    75 50,
                    70 50,
                    65 55,
                    65 60,
                    60 60,
                    55 65,
                    50 60,
                    45 60,
                    45 55,
                    40 50,
                    35 50,
                    30 55,
                    25 50,
                    20 50,
                    25 45,
                    20 40,
                    30 40,
                    35 35,
                    30 30,
                    20 30,
                    25 25,
                    20 20,
                    25 20,
                    30 15,
                    35 20,
                    40 20,
                    45 15,
                    45 10,
                    50 10,
                    55 5" />
  <foreignObject x="0" y="0" requiredExtensions="http://www.w3.org/1999/xhtml">

    <body xmlns="http://www.w3.org/1999/xhtml">
      <p>Here is a paragraph that requires word wrap</p>
    </body>
  </foreignObject>
</svg>

I could not get the <foreignObject> to work and even if I did it's not supported in IE browsers.
There is no need to support old IE browsers, but I would like support in at least one of them.
Also minor detail at the top, the shape is not closed.

Then I tried creating a snowflake in it with CSS:

.snowflake {
  position: absolute;
  width: 200px;
  display: inline-block;
  border-bottom: 10px solid cornflowerblue;
  top: 200px;
  left: 100px;
  background-color: white;
}
.snowflake:before {
  position: absolute;
  content: "";
  display: inline-block;
  width: 50px;
  border-bottom: 10px solid cornflowerblue;
  transform: rotate(45deg);
  top: -20px;
}
.snowflake:after {
  position: absolute;
  content: "";
  display: inline-block;
  width: 50px;
  border-bottom: 10px solid cornflowerblue;
  transform: rotate(-45deg);
  top: 20px;
}
.smallbranch {
  position: absolute;
  right: 0px;
  display: inline-block;
  width: 50px;
  border-bottom: 10px solid cornflowerblue;
  transform: rotate(45deg);
  top: 17px;
  box-shadow: -130px -5px 0px 0px cornflowerblue;
}
.smallbranch:before {
  position: absolute;
  content: "";
  display: inline-block;
  width: 50px;
  border-bottom: 10px solid cornflowerblue;
  transform: rotate(90deg);
  top: -22px;
  left: -22px;
  box-shadow: 130px -5px 0px 0px cornflowerblue;
}
.circle {
  position: absolute;
  left: 50%;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  border: 5px solid cornflowerblue;
  background-color: white;
  transform: translate(-50%, -50%);
}
.circle:before {
  position: absolute;
  content: "";
  display: inline-block;
  width: 50px;
  border-bottom: 10px solid cornflowerblue;
  transform: rotate(90deg);
  top: -52px;
  left: 20px;
  transform: rotate(-45deg);
}
.circle:after {
  position: absolute;
  content: "";
  display: inline-block;
  width: 50px;
  border-bottom: 10px solid cornflowerblue;
  transform: rotate(90deg);
  top: 102px;
  left: 20px;
  transform: rotate(45deg);
}
.branch {
  position: absolute;
  display: inline-block;
  height: 200px;
  border-right: 10px solid cornflowerblue;
  left: 50%;
  top: -100px;
}
<div class="snowflake">
  <div class="branch"></div>
  <div class="smallbranch"></div>
  <div class="circle">Text in here</div>
</div>

This was my best attempt with CSS.
Now here the text is displayed but its not on one line. My idea is to use this in a logo or for a button on the webpage. So I don't think I will need line wrap functionality on the shape, but it would be a plus if it had.

The shape I would like created:
enter image description here

TL;DR
What I would like is a snowflake with text in the middle of the shape.
I'm asking for a solution where the text could be any length and still be inside the shape.
You don't have to create a shape that's exactly the same as what I have tried as long as the shape is a snowflake with text in the center it's ok. I don't know how long the text will be so the shape has to contain the text.

like image 237
Persijn Avatar asked Oct 21 '15 16:10

Persijn


2 Answers

My solution uses part SVG, part HTML/CSS to create the effect required.

I have used the calc() CSS3 function along with viewport based width/height units which then give it the responsiveness required.

It looks much better when the element is above 200px wide.

  • calc() Browser Support
  • Viewport Units Browser Support

The Code

.container {
  position: relative;
  overflow: auto;
  display: block;
  width: 50vw;
  height: 50vw;
}
.container svg {
  width: 100%;
  height: 100%;
  position: absolute;
}
p {
  position: absolute;
  z-index: 100;
  background: white;
  left: 17.5vw;
  top: 17.5vw;
  margin: 0;
  padding: 10px 0;
  width: 10vw;
  text-align: center;
  font-size: 2vw;
  border: 20px solid black;
}
@media screen and (min-width: 920px) {
  p {
    font-size: 3vw;
    width: 12.5vw;
  }
}
<div class="container">
  <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve" width="50%">
    <polygon id="christmas-snowflake-icon" points="441.535,346.644 373.955,307.624 438.697,290.354 431.342,262.782 338.967,287.424
284.535,255.999 339.49,224.271 431.299,249.242 438.787,221.705 374.311,204.168 441.535,165.356 427.266,140.644 359.686,179.66
377.1,114.956 349.545,107.541 324.697,199.861 270.27,231.285 270.27,167.831 337.797,100.809 317.695,80.554 270.27,127.624
270.27,50 241.732,50 241.732,128.036 194.404,80.604 174.203,100.76 241.732,168.438 241.732,231.286 186.779,199.558
162.498,107.565 134.906,114.847 151.957,179.455 84.732,140.644 70.465,165.356 138.045,204.373 73.303,221.645 80.66,249.218
173.035,224.574 227.465,255.999 172.51,287.727 80.701,262.758 73.211,290.293 137.688,307.832 70.465,346.644 84.732,371.356
152.312,332.337 134.898,397.042 162.457,404.459 187.303,312.137 241.732,280.711 241.732,344.169 174.203,411.191
194.307,431.446 241.732,384.376 241.732,462 270.27,462 270.27,383.964 317.598,431.396 337.797,411.24 270.27,343.562
270.27,280.712 325.223,312.439 349.502,404.435 377.094,397.15 360.043,332.545 427.268,371.356 "></polygon>
  </svg>
  <p>This is some text Now</p>
</div>

CodePen

like image 27
Stewartside Avatar answered Oct 12 '22 12:10

Stewartside


Play with this demo

This is actually a quite interesting question, and coming up with an answer was not easy.

The question asks to make a shape(in this case a snowflake), that would scale to fit the text inside of it. My first advice is to use an image, not try and create the shape with CSS. Images are much easier to make scale, and can have more detail then a CSS shape.

So, lets show how we can accomplish this.

First of all, since you want the element to scale to fit the font, we need to make the element display:inline-block. This will make it only be as wide as it's content, unlike block which would make it as wide as it's parent, and still be able to set the height(which you cannot do with inline).

Next, we need to make the element with a height the same as the width. Luckily, there is a trick in CSS that allows you to do just that. The padding of an element is calculated based on it's width, so if you set the padding-bottom(or padding-top) to 100%, it will have the same width as height.(See this excellent SO answer for further info).

After this, it is just a matter of centering the text inside the snowflake, which may take a little playing with the values to fit your font-family.

If you want the jsfiddle with code: JSFiddle Demo

Full-Screen JSFiddle Demo

Tested in Chrome, FireFox, IE, and Safari. Minor adjustments may be needed for certain font-family's

.snowflake{
    display:inline-block;
      background:url("http://i.imgur.com/4M9MH1Q.png") scroll no-repeat center/contain;
    }
/*This is for setting the height the same as the width, a 1:1 ratio. more info http://www.mademyday.de/css-height-equals-width-with-pure-css.html#outer_wrap */
    .snowflake:after{
    	content: "";
    	display: block;
    	padding-top: 100%;
    }
    .snowflake span{
        display:inline-block;
        -webkit-transform: translateY(110%);
            -ms-transform: translateY(110%);
                transform: translateY(110%);
        width:100%;
        text-align:center;
       padding-top:20%;
      }
/*This part is ugly, but it is required to work in chrome or IE, you may have to change the char for different font types*/
 .snowflake span:before, .snowflake span:after{
     content:"aaa";
     visibility:hidden;
     opacity:0;
  }
        Font-size 12pt:
    <div class="snowflake" style="font-size:12pt;">
      <span>It's Snowing!</span>
    </div>
    Font-size 24pt:
    <div class="snowflake" style="font-size:24pt;">
      <span>It's Snowing!</span>
    </div>
    Font-size 48pt:
    <div class="snowflake" style="font-size:48pt;">
      <span>It's Snowing!</span>
    </div>

EDIT: This solution is prettier, but doesn't work in Chrome or IE

.snowflake{
display:inline-block;
  background:url("http://i.imgur.com/4M9MH1Q.png") scroll no-repeat center/contain;
}
/*This is for setting the height the same as the width, a 1:1 ratio. more info http://www.mademyday.de/css-height-equals-width-with-pure-css.html#outer_wrap */
.snowflake:after{
	content: "";
	display: block;
	padding-top: 100%;
}
.snowflake span{
  display:inline-block;
    transform: translateY(90%);
  padding:20%;
  }
Font-size 12pt:
<div class="snowflake" style="font-size:12pt;">
  <span>It's Snowing!</span>
</div>
Font-size 24pt:
<div class="snowflake" style="font-size:24pt;">
  <span>It's Snowing!</span>
</div>
Font-size 48pt:
<div class="snowflake" style="font-size:48pt;">
  <span>It's Snowing!</span>
</div>

The main condition for this to work is:

.snowflake must be display:inline-block;

Full-Screen JSFiddle Demo

like image 169
Jacob Gray Avatar answered Oct 12 '22 11:10

Jacob Gray