Can i exclude spaces from text decoration? - css

Maybe my question is too simple :) Struggling to exclude &snbsp and spaces from being visualized with strike through:
del {
text-decoration: line-through;
background-color: var(--color-warn-light);
}
So in <del>&nbsp</del> the space is not visualized like a minus '-'.
Is there a possibility that CSS can be used to exclude some characters from being decorated?
Update: found text-decoration-skip: spaces by its is not supported by most browsers :(

As you and #dippas figured out, this is currently not supported via pure CSS across all browsers.
I suggest doing this with JavaScript, by splitting the text you are interested in at the space character into separate span elements. You can then apply your line-through decoration to the span elements, which will not include the spaces.
Here is a simple example:
const elements = document.querySelectorAll("del");
for (let i = 0; i < elements.length; i++) {
const elem = elements[i];
const words = elem.innerText.split(" ");
const spans = words.map((word) => {
const span = document.createElement("span");
span.innerText = word;
return span;
});
elem.innerHTML = "";
spans.forEach((span) => {
elem.appendChild(span);
elem.innerHTML += " ";
});
}
del {
text-decoration: none;
}
del span {
text-decoration: line-through;
}
<div>
<del>All the text to be marked through here</del>
<br />
<del>Additional text to be marked through here</del>
</div>

Inline Block
You can wrap the space in a span with display set to inline-block:
span {
display: inline-block;
}
<del>text<span>&nbsp</span>text</del>
Selector :not
span:not(.space) {
text-decoration: line-through;
}
<span>text</span>
<span class="space">&nbsp</span>
<span>text</span>
JavaScript
Or you can use some simple JavaScript:
const elements = document.querySelectorAll("del");
for (let i = 0; i < elements.length; i++) {
const elem = elements[i];
const words = elem.innerText.split(/\s/);
elem.innerHTML = words.join("<span> </span>")
}
span {
display: inline-block;
}
<del>text text</del>
<del>text text</del>

Related

CodeMirror Line-Break doesn't add line number - Angular

I'm using code mirror from ngx-codemirror. I want to split the line when it fits to the width of the parent. I have found some solutions to split the like using,
lineWrapping: true
and in styles
.CodeMirror-wrap pre {
word-break: break-word;
}
Using this I was able to split the line but I need to show the line number too.
The line number is not shown for the line that was just split.
This is the stackblitz link to my issue : code-mirror-line-break-issue
Screenshot :
Please help me with this.
This is not feasible using Code Mirror options, as this is something that is a bit counter intuitive that is rarely (ever?) wanted.
Like I said in my comment, say 2 persons discussing on a phone/web chat about a piece of code/json. They will not see the same thing when one mentions a line number to the other if they have different windows/screen sizes
Solution
As a hack, you can create your own elements representing line numbers and place them over the default line numbers.
Here is the stackblitz demo
Note: This a a very basic example. If you change code mirror settings (font size, gutters,...), you might need to tweak the css or do more calculation based on these settings.
component.html
<div class='codeMirrorContainer'>
<ngx-codemirror
#codeMirror
[options]="codeMirrorOptions"
[(ngModel)]="codeObj"
></ngx-codemirror>
<ul class='lineContainer' [style.top.px]="-topPosition">
<li [style.width.px]='lineWidth' *ngFor="let line of lines">{{line}}</li>
</ul>
</div>
component.css
li
{
height: 19px;
list-style: none;
}
.codeMirrorContainer
{
position:relative;
overflow: hidden;
}
.lineContainer
{
position:absolute;
top:0;
left:0;
margin: 0;
padding: 5px 0 0 0;
text-align: center;
}
::ng-deep .CodeMirror-linenumber
{
visibility: hidden; /* Hides default line numbers */
}
component.ts
export class AppComponent
{
#ViewChild('codeMirror') codeMirrorCmpt: CodemirrorComponent;
private lineHeight: number;
public lineWidth;
public topPosition: number;
public lines = [];
codeMirrorOptions: any = ....;
codeObj :any = ...;
constructor(private cdr: ChangeDetectorRef)
{
}
ngAfterViewInit()
{
this.codeMirrorCmpt.codeMirror.on('refresh', () => this.refreshLines());
this.codeMirrorCmpt.codeMirror.on('scroll', () => this.refreshLines());
setTimeout(() => this.refreshLines(), 500)
}
refreshLines()
{
let editor = this.codeMirrorCmpt.codeMirror;
let height = editor.doc.height;
this.lineHeight = editor.display.cachedTextHeight ? editor.display.cachedTextHeight : this.lineHeight;
if (!this.lineHeight)
{
return;
}
let nbLines = Math.round(height / this.lineHeight);
this.lines = Array(nbLines).fill(0).map((v, idx) => idx + 1);
this.lineWidth = editor.display.lineNumWidth;
this.topPosition = document.querySelector('.CodeMirror-scroll').scrollTop;
this.cdr.detectChanges();
}
}

How to apply css to the property of the tag?

I am new to css and i would like to know if css can be applied to the properties of tag?
For example in the below code i would like to see entry.count and "files" in blue color.
code
render() {
return(
<div className="AppL" id="AppList">
{this.createApplicationList()}
</div>);
}
createApplicationList() {
var guiResult = [];
for (var key in this.state.AppName) {
var entry = this.state.AppName[key];
guiResult.push(
<Collapsible trigger={entry.AppName + "\t" + "\t" + entry.Count + " files"} className="AppList" transitionTime ="10">
</Collapsible>);
};
return guiResult;
}
my scss for this component
.AppList{
color: black;
border-bottom: 1px solid #00a886;
padding-top:10px;
padding-bottom:10px;
}
.Collapsible .Collapsible__trigger {
color: blue;
}
.Collapsible selects all elements with the Collapsible class. Collapsible_trigger does the same for the Collapsible__trigger class. Together, the rule selects all .Collapsible__trigger elements within .Collapsible elements, and styles them with blue text.
This is based purely on your provided HTML code. The JavaScript appears to be irrelevant.
.Collapsible .Collapsible__trigger.is-closed also works and is more specific. Depends on your use-case.

Make Different Fonts Display at the Same Actual Size?

When I use two different fonts in a web page at the same font-size, they often display at different actual sizes:
This example uses two Google Fonts, Gentium and Metamorphous at the same font-size, specified as 20px.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<link id="Gentium Book Basic" rel="stylesheet" type="text/css"
href="http://fonts.googleapis.com/css?family=Gentium Book Basic"
media="all">
<link id="Metamorphous" rel="stylesheet" type="text/css"
href="http://fonts.googleapis.com/css?family=Metamorphous" media="all">
</head>
<body style="font-size: 20px">
<span style="font-family: Gentium Book Basic">Test Text Length (Gentium)</span>
<br>
<span style="font-family: Metamorphous">Test Text Length (Metamorphous) </span>
</body>
</html>
A JSBin for this example can be found here.
My understanding of specifying font-size in an absolute length like px was that the font would be scaled to match that length. My expectation is that two different fonts at the same font-size would have either matching height or matching length (I understand the aspect ratios of the fonts may be different). But it doesn't appear that either is the case here. Is there some way I can make two arbitrary fonts display at either the same height or the same length without manually calculating and applying a correction?
EDIT: An example showing the descender to ascender distance for two fonts displayed at the same font size.
Clearly the two distances are not the same for these two fonts as displayed.
EDIT: An example showing letters with and without accents in the two fonts:
Again, clearly the letters are different sizes.
EDIT: Going on what is described in this article, the issue is that font-size controls the displayed size of the em value of the font. But the em value is arbitrary (it doesn't have to correspond to anything within the font, and in particular is not necessarily the height of a lower case 'm'), and does not include the ascenders and descenders, which can be any size at all (example taken from above article):
so the result is that a "100px" font can be just about any effective size whatsoever. The author of the above article computed the range of effective sizes for the Google Web Fonts at the time to be 0.618 to 3.378.
Since the font metrics (such as the em size, the capitals height, the ascender and descender values) are not exposed in CSS, there doesn't seem to be any way within CSS to make two arbitrary fonts the same effective size. For any particular font, you can use a font editor to find the font metric values and use those numbers to scale the font as required. For an arbitrary font, an option is to display some text and use the measured bounding box to determine the effective size and calculate an appropriate scaling factor.
My thanks to everyone who contributed to explaining this!
I spent a lot of time crawling through StackOverflow looking for answers for a similar situation and ended up not finding anything perfect. What I ended up doing is measuring the two fonts, and then adjusting the top margin and scale of the second font to match the first. (By using scale instead of changing the font size, it allows us to not need to re-calculate the text metrics after resizing)
I put together a couple of pens for posterity. Here's the second one, which handles the normalization of font sizes and alignments between two fonts: https://codepen.io/zacholas/pen/oNBPWga
And the first one, that only handles the measuring, is: https://codepen.io/zacholas/pen/ExZwJjx
I guess I have to paste some code in order to link to codepen, so here's all the comparison code:
HTML:
<h1>Welcome</h1>
<p>
<strong>What's all this about?</strong><br>
I've been working on the new version of the Mason image editor app, and in it, I need to compare multiple fonts to replace them with each other to have the final layout not look crappy due to spacing differences between fonts. (To allow users to customize fonts in templates and have them still look nice)
</p>
<p>The first pen focused on getting all the measurements and ratios necessary.</p>
<p>This pen encompasses the second part, which is comparison and normalization of different fonts against a default.</p>
<p>
<strong>How it works</strong><br>
First we get the metrics for the two fonts and compare their top/bottom spacing. We then normalize them to align in a purdy vertically-centered way. And then we scale down the second font's container so that it matches the size of the first.
</p>
<p>Enjoy!</p>
<p><em>- Zach</em></p>
<hr>
<h3>Demo</h3>
<p>If all of my code is working correctly, the text in the "new font adjusted" box should look all purdy and be vertically and horizontally centered.</p>
<p><strong>NOTE:</strong><em> You'll need to make a change in the dropdown before the text in the "new font adjusted" box actually gets adjusted.</em></p>
<label for="font-picker">Choose a font to swap:</label>
<select id="font-picker" disabled>
<option value=""> — Template Default — </option>
</select>
<div >
<div id="image-box" class="flex-row">
<div>
<h6>Original:</h6>
<div class="reference-box">
<div class="text-background">
<div class="text-container text-utc-lander" id="original-text">
Hxy
</div>
</div>
</div>
</div>
<div>
<h6>New font unadjusted:</h6>
<div class="reference-box">
<div class="text-background">
<div class="text-container text-utc-lander" id="unadjusted-text">
Hxy
</div>
</div>
</div>
</div>
<div>
<h6>New font adjusted:</h6>
<div id="modified" class="reference-box">
<div class="text-background">
<div class="scaler" id="adjusted-text-scaler">
<div class="text-container text-utc-lander" id="adjusted-text">
Hxy
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<hr>
<h2>Canvases used for calculating</h2>
<div id="sample-output-container">
</div>
SCSS:
#import 'https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css';
// The font size in the demo boxes
$test-font-size: 200px!default;
// $test-font-size: 100px;
body {
background: #eee;
padding: 10px;
font-family: Arial;
}
hr {
margin: 40px 0;
}
h6 {
font-size: 17px;
margin: 12px 0 5px 0;
}
//* In production, you should probably use code like this to position canvases off-screen:
// .test-canvas {
// position: fixed;
// top: -99999px;
// left: -99999px;
// display:none;
// }
.text-utc-lander { font-family: 'UTCLander-Regular'; }
.text-ar-bonnie { font-family: 'ARBONNIE'; }
.text-adam-cg { font-family: 'ADAMCGPRO'; }
.text-abolition { font-family: 'Abolition-Regular'; }
.text-avenir { font-family: 'AvenirNextLTPro-BoldItalic'; }
.text-agency { font-family: 'AgencyFB-Reg'; }
/* Testing a real life example with absolute CSS done to make a F-ed up font
like UTC lander look good, which we'll then need to modify positioning and
sizing for in order for it to look good with normal fonts */
.flex-row {
display: flex;
justify-content: space-between;
}
#image-box {
.reference-box {
background: url('https://mason-app-staging.herokuapp.com/images/sports_stadium_generic.jpg');
background-size: cover;
position: relative;
width: $test-font-size * 2;
height: $test-font-size * 1.2;
&:before, &:after {
content: '';
left: $test-font-size * .1;
right: $test-font-size * .1;
position: absolute;
height: 1px;
background: rgba(0,0,0,0.1);
z-index: 5;
}
&:before {
top: $test-font-size * 0.245;
}
&:after {
bottom: $test-font-size * 0.245;
}
.text-background {
position: absolute;
left: ($test-font-size * 0.1);
top: ($test-font-size * 0.1);
width: ($test-font-size * 1.8);
height: ($test-font-size * 1);
background:#39b510;
color: #fff;
text-transform: uppercase;
display: flex;
align-items: center;
justify-content: center;
}
.text-container {
margin-top: -10px; // Will be overwritten anyway
text-align: center;
font-size: $test-font-size;
line-height: 1;
}
}
}
#comparison-output {
background: #fff;
padding: 20px;
margin-top: 40px;
flex: 1;
}
//* Debug output from the first example
#sample-output-container {
// * {
// line-height: 1;
// }
> div {
width: 700px;
background: #CCC;
margin-bottom: 20px;
position: relative;
height: 200px;
> .text-container {
background: #fff;
position: absolute;
display: flex;
height: 150px;
left: 25px;
width: 300px;
top: 25px;
align-items: center;
justify-content: center;
> span {
background: #edc79e;
}
}
> .info-box {
font-size: 12px;
font-family: Arial;
background: #fff;
position: absolute;
width: 300px;
top: 25px;
right: 25px;
padding: 10px;
}
}
}
/*
Webfonts
- Code from here down is just base 64'd webfonts.
- All are in "normal" font weight
- Families available:
- 'ARBONNIE';
- 'ADAMCGPRO';
- 'Abolition-Regular';
- 'AgencyFB-Reg';
- 'AvenirNextLTPro-BoldItalic';
- 'UTCLander-Regular';
*/
/* ***** SKIPPING BASE-64'D FONTS FOR STACKOVERFLOW */
JS:
import FontFaceObserver from "https://cdn.skypack.dev/fontfaceobserver#2.1.0";
// var FontFaceObserver = require('fontfaceobserver');
const TYPE_DEFAULT_FONT = 'defaultFont';
const TYPE_CURRENT_FONT = 'currentFont';
// debug output canvases
const removeCalculationCanvases = false;
const allAvailableFonts = [
{ label: 'AR Bonnie', value: 'ARBONNIE' },
{ label: 'Adam CG Pro', value: 'ADAMCGPRO' },
{ label: 'Abolition Regular', value: 'Abolition-Regular' },
{ label: 'Avenir Next LT Pro Bold Italic', value: 'AvenirNextLTPro-BoldItalic' },
{ label: 'Agency FB', value: 'AgencyFB-Reg' },
{ label: 'UTC Lander', value: 'UTCLander-Regular' },
]
const INITIAL_STATE = {
[TYPE_DEFAULT_FONT]: {
label: null,
fontFamily: null,
fontSize: null,
metrics: {},
},
[TYPE_CURRENT_FONT]: {
label: null,
fontFamily: null,
fontSize: null,
metrics: {},
postAdjustmentMetrics: {}
}
}
let state = {
...INITIAL_STATE
}
const _roundToTwo = num => {
return +(Math.round(Number(num) + "e+2") + "e-2");
}
const _roundToFive = num => {
return +(Math.round(Number(num) + "e+5") + "e-5");
}
function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
const getTextMetrics = async(fontFamily, fontSize, testtext = 'Sixty Handgloves ABC') => {
//* For now we'll just keep the test text hard-coded but maybe we'll pass in the element value at some point. (However, being that the text will be editable I don't think that's wise)
testtext = 'Hxy';
const fontSizePx = fontSize.split('px')[0];
//* Generate a hash from the font name for the canvas ID
const canvasId = Math.abs(fontFamily.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0));
console.log('waiting for font to load')
var font = new FontFaceObserver(fontFamily);
await font.load();
console.log('font loaded');
//* Initialize the test canvas so that we can measure stuff
const testCanvasWidth = 400;
const testCanvasHeight = 200;
const testCanvasPadding = 10;
// const canvasDrawingTextFontSize = 1000;
const canvasDrawingTextFontSize = fontSizePx;
const testCanvas = document.createElement('canvas');
testCanvas.id = (`cvs-${canvasId}-${Math.random().toString(36).substring(7)}`);
testCanvas.className = `test-canvas ${canvasId}`;
testCanvas.width = testCanvasWidth;
testCanvas.height = testCanvasHeight;
// document.body.appendChild(testCanvas);
var testCanvasCtx = testCanvas.getContext("2d");
testCanvas.style.font = `${canvasDrawingTextFontSize}px ${fontFamily}`;
testCanvasCtx.font = [`${canvasDrawingTextFontSize}px`, fontFamily].join(' ');
testCanvasCtx.clearRect(0, 0, testCanvasWidth, testCanvasHeight);
testCanvasCtx.fontFamily = fontFamily;
testCanvasCtx.fillStyle = "#fff";
testCanvasCtx.fillRect(0,0,testCanvas.width, testCanvas.height);
testCanvasCtx.fillStyle = "#333333";
testCanvasCtx.fillText(testtext, testCanvasPadding, testCanvasHeight);
// console.log('before timeout');
// await timeout(3000);
// console.log('timeout done');
document.body.appendChild(testCanvas);
//* Get Core Measurements
var xHeight = testCanvasCtx.measureText("x").height;
var capHeight = testCanvasCtx.measureText("H").height;
// var measuredTextMetrics = testCanvasCtx.measureText("Hxy");
var measuredTextMetrics = testCanvasCtx.measureText(testtext);
//* Make the measurements usable (cast to numbers to allow for nulls)
let metrics = {};
metrics.measured = {
actualBoundingBoxAscent: _roundToFive(measuredTextMetrics.actualBoundingBoxAscent),
actualBoundingBoxDescent: _roundToFive(measuredTextMetrics.actualBoundingBoxDescent),
actualBoundingBoxLeft: _roundToFive(measuredTextMetrics.actualBoundingBoxLeft),
actualBoundingBoxRight: _roundToFive(measuredTextMetrics.actualBoundingBoxRight),
fontBoundingBoxAscent: _roundToFive(measuredTextMetrics.fontBoundingBoxAscent),
fontBoundingBoxDescent: _roundToFive(measuredTextMetrics.fontBoundingBoxDescent),
width: _roundToFive(measuredTextMetrics.width)
};
const fontSizeMultiplicand = fontSizePx / canvasDrawingTextFontSize;
const {
actualBoundingBoxAscent,
// actualBoundingBoxDescent,
// actualBoundingBoxLeft,
// actualBoundingBoxRight,
fontBoundingBoxAscent,
fontBoundingBoxDescent,
} = metrics.measured;
metrics.calculated = {
gapAboveText: _roundToFive((fontBoundingBoxAscent - actualBoundingBoxAscent) * fontSizeMultiplicand),
gapBelowText: _roundToFive(fontBoundingBoxDescent * fontSizeMultiplicand),
textHeight: _roundToFive(actualBoundingBoxAscent * fontSizeMultiplicand),
totalHeight: _roundToFive((fontBoundingBoxAscent + fontBoundingBoxDescent) * fontSizeMultiplicand),
};
const {
gapBelowText, gapAboveText, textHeight, totalHeight
} = metrics.calculated;
metrics.calculated.gapBelowTextPercent = _roundToFive(gapBelowText / totalHeight);
metrics.calculated.gapAboveTextPercent = _roundToFive(gapAboveText / totalHeight);
metrics.calculated.gapTopBottomRatio = _roundToFive(gapAboveText / gapBelowText);
metrics.calculated.textHeightPercent = _roundToFive(textHeight / totalHeight);
metrics.calculated.baselineMarginTop = gapBelowText - gapAboveText;
if(removeCalculationCanvases === true){
testCanvas.remove(); // cleanup
}
return metrics;
};
const setFontState = async(fontFamily, fontSize, fontLabel, type = TYPE_CURRENT_FONT) => {
if(fontFamily){
console.log('about to get text metrics')
const metrics = await getTextMetrics(fontFamily, fontSize);
console.log('metrics received');
state[type] = {
label: fontLabel ? fontLabel : fontFamily,
fontFamily,
fontSize,
metrics
}
}
else {
state[type] = {
...INITIAL_STATE[type]
}
}
return true;
}
const watchForFontChange = async() => {
document.addEventListener('input', async(event) => {
if (event.target.id !== 'font-picker') return; // Only run on the font change menu
let label = null;
if(
event.target.options.length &&
typeof event.target.options[event.target.selectedIndex] !== 'undefined' &&
event.target.options[event.target.selectedIndex].text
) {
label = event.target.options[event.target.selectedIndex].text;
}
// For now just grab font size from the default font state, but probably will change later
const fontFamily = event.target.value;
const fontSize = state[TYPE_DEFAULT_FONT].fontSize;
await setFontState(fontFamily, fontSize, label);
console.log('font changed', state);
//* Set the font families in the display
if(fontFamily){
document.getElementById(`unadjusted-text`).style.fontFamily = fontFamily;
document.getElementById(`adjusted-text`).style.fontFamily = fontFamily;
}
else {
document.getElementById(`unadjusted-text`).style.fontFamily = null;
document.getElementById(`adjusted-text`).style.fontFamily = null;
}
//* Calculate the adjustments for the new font compared to the baseline
// const currentFontSize = parseInt(state.currentFont.fontSize,10);
const defaultFontMetrics = state.defaultFont.metrics;
const currentFontMetrics = state.currentFont.metrics;
// const fontSizeAdjustPx = defaultFontMetrics.calculated.textHeight - currentFontMetrics.calculated.textHeight;
// const fontSizeAdjustPcnt = _roundToFive(fontSizeAdjustPx / currentFontMetrics.calculated.textHeight);
//* Apply the adjustments
// const newFontSize = currentFontSize + (currentFontSize * fontSizeAdjustPcnt);
// console.log('newFontSize', newFontSize);
const textToAdjust = document.getElementById(`adjusted-text`);
// const fontSizeStr = `${newFontSize}px`;
textToAdjust.style.marginTop = `${currentFontMetrics.calculated.baselineMarginTop}px`;
const scaler = document.getElementById('adjusted-text-scaler');
const scale = _roundToTwo(defaultFontMetrics.calculated.textHeight / currentFontMetrics.calculated.textHeight);
scaler.style.transform = `scale(${scale})`;
}, false);
}
const addFontOptionsToDropdown = () => {
const parentSelect = document.getElementById(`font-picker`);
for(let i=0; i < allAvailableFonts.length; i++){
const thisOption = allAvailableFonts[i];
if(thisOption.value){
const label = thisOption.label ? thisOption.label : thisOption.value;
const thisOptionTag = document.createElement("option");
thisOptionTag.value = thisOption.value;
const thisOptionText = document.createTextNode(label);
thisOptionTag.appendChild(thisOptionText);
parentSelect.appendChild(thisOptionTag);
}
}
}
const parseDefaultFont = async() => {
const thisText = document.getElementById(`original-text`);
// We might need to do some special stuff for uppercase vs non-uppercase text
const thisTextStyle = window.getComputedStyle(thisText);
const textTransform = thisTextStyle.getPropertyValue('text-transform');
const marginTop = thisTextStyle.getPropertyValue('margin-top');
console.log('marginTop', marginTop);
const uppercase = textTransform === 'uppercase';
const fontFamily = thisTextStyle.getPropertyValue('font-family');
const fontSize = thisTextStyle.getPropertyValue('font-size');
console.log('fontSize', fontSize);
await setFontState(fontFamily, fontSize, null, TYPE_DEFAULT_FONT);
document.getElementById(`original-text`).style.marginTop = `${state.defaultFont.metrics.calculated.baselineMarginTop}px`;
return !! fontFamily;
}
const init = async() => {
console.log(' ');
console.log(' ');
console.log(' ');
console.log('initialized.');
const defaultFont = await parseDefaultFont();
if(defaultFont){
addFontOptionsToDropdown(); // Parse JSON object into the select html tag
await watchForFontChange();
}
else {
// Handle Error -- for some reason there wasn't a font family for the default text.
}
document.getElementById('font-picker').disabled = false;
console.log('state after init done', state);
}
//* Wait for all the base 64'd fonts to load before we run it
document.addEventListener("DOMContentLoaded", (ready => {
init();
// setTimeout(function(){ init(); }, 1000);
}));
Think of the font-size not as the actual size of the individual characters themselves, but as the size of the blocks that contain each character, just like typeset letters:
The size of the blocks is defined in your CSS (using px, pts, ems, etc) but the actual size of the characters within those blocks can vary depending on the font used.
The actual, physical height of any given portion of the font depends on the user-defined DPI setting, current element font-size, and the particular font being used.
https://en.wikipedia.org/wiki/Em_(typography)#CSS
You can use the font-size-adjust property to help alter one of those fonts to scale it closer to the other: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size-adjust although its support is currently limited to Firefox: http://caniuse.com/#feat=font-size-adjust
Font size is the size of the glyph from the ascender, such as the top of the letter 'h', to the descender, such as the bottom of the letter 'g'. If you set your font size to 20px, the length from the top of the letter 'h' to the bottom of the letter 'g' will be 20px. Some letters have terminals or spurs, the ends of a letter, may extend a px or two higher on some letters.
In your example, there is a px difference between the two fonts. The Metamorphous font has a mark above some letters that Gentium does not have and that is what accounts for the height difference.
You can read more here.
EDIT: See here with the "caron" above the C compared to the two Gentium letters on the right.
you should rather use something like rem then px :) as rem is a relative measure unit and px is absolute. But fonts always have a different size and imo its not possible what you want to achieve.

How to Capitalize first letter only using CSS in each case

I want to Capitalize first letter only and other should be small using CSS
String is:
SOMETHING BETTER
sOMETHING bETTER
Something better
but the result should be
Something Better
Is this possible using CSS? To Capitalize first letter I am using
text-transform: capitalize;
But not able to capitalize in each case.
"I want to use CSS because in my application it has written every where hard coded but a class has been called everywhere."
you should be able to use the :first-letter pseudo element:
.fl {
display: inline-block;
}
.fl:first-letter {
text-transform:uppercase;
}
<p>
<span class="fl">something</span> <span class="fl">better</span>
</p>
yields:
Something Better
It is not possible with CSS alone but you can do it with Javascript or PHP for example.
In PHP
ucwords()
And in Javascript
function toTitleCase(str){
return str.replace(/\w\S*/g, function(txt){
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}
Extracted from
Convert string to title case with JavaScript
You can try a combination of this answer and some javascript (using jQuery)
HTML:
<div class='capitalize'>
SOMETHING BETTER
SOMETHING BETTER
SOMETHING BETTER
</div>
JAVASCRIPT:
$('.capitalize').each(function(){
var text = this.innerText;
var words = text.split(" ");
var spans = [];
var _this = $(this);
this.innerHTML = "";
words.forEach(function(word, index){
_this.append($('<span>', {text: word}));
});
});
CSS:
.capitalize {
text-transform: lowercase;
}
.capitalize span {
display: inline-block;
padding-right: 1em
}
.capitalize span:first-letter {
text-transform: uppercase !important;
}
Demo: http://jsfiddle.net/maniator/ZHhqj/
Why dont you just use the :first-letter pseudo element in css?
h2:first-letter{
text-transform: uppercase;
}
h2{
*your general code for h2 goes here;*
}
Yes, CSS is no help here. Welcome to the world of JavaScript, where anything is possible.
window.onload = function(){
var elements = document.getElementsByClassName("each-word")
for (var i=0; i<elements.length; i++){
elements[i].innerHTML = elements[i].innerHTML.replace(/\\b([a-z])([a-z]+)?\\b/gim, "<span class='first-letter'>$1</span>$2")
}
}
.first-letter {
color: red;
}
<p class="each-word">First letter of every word is now red!</p>

Margin, position and padding not working when display:inline is set. also weird behaviour from relative position

I have two CSS classes:
.class1 {
height: 100%;
width: 300px;
border: 1px none #B0B0B0;
position: relative;
display: inline;
left: 10px;
}
.class2 {
height: 100%;
width: 200px;
position: relative;
display: inline;
margin-left: 15px;
background-color: #00CCCC;
border-top-width: 1px;
border-right-width: 1px;
border-bottom-width: 1px;
border-left-width: 1px;
border-top-style: solid;
border-right-style: solid;
border-bottom-style: solid;
border-left-style: solid;
}
Now, as you can see, they're both set to display in a line (no line breaks in between elements). Which works correctly. But for some reason, ever since I set the display to inline, the Padding, the Positioning and the Margin CSS have all just stopped working. I can add a margin-left 10inches and nothing will happen. Same with padding and positioning.
Can anyone explain how to fix this?
Also, I have the relative position set on both classes, yet when viewing the page in a browser, .class2 over laps .class1 when its supposed to be just after .class1.
Any ideas?
EDIT:
Okay, so I've done a JSFiddle, but it seems to be playing up even more there....
Looks like the Width is not working....
here it is:
http://jsfiddle.net/zYbwh/1/
You need to use
display: inline-block;
instead. margin doesn't work with display: inline elements, however with inline-block it does. You can then have an inline element with margins and explicit widths/heights.
To make this work in IE7, add these two lines:
*display: inline;
zoom: 1;
It's horrible, but it works.
I know this is quite a late answer but I wrote a jQuery plugin which support padding on inline elements (with word breaking) see this JSfiddle:
http://jsfiddle.net/RxKek/
Plugin Code:
$.fn.outerHTML = function () {
// IE, Chrome & Safari will comply with the non-standard outerHTML, all others (FF) will have a fall-back for cloning
return (!this.length) ? this : (this[0].outerHTML || (
function (el) {
var div = document.createElement('div');
div.appendChild(el.cloneNode(true));
var contents = div.innerHTML;
div = null;
return contents;
})(this[0]));
};
/*
Requirements:
1. The container must NOT have a width!
2. The element needs to be formatted like this:
<div>text</div>
in stead of this:
<div>
text
</div>
*/
$.fn.fixInlineText = function (opt) {
return this.each(function () {
//First get the container width
var maxWidth = opt.width;
//Then get the width of the inline element
//To calculate the correct width the element needs to
//be 100% visible that's why we make it absolute first.
//We also do this to the container.
$(this).css("position", "absolute");
$(this).parent().css("position", "absolute").css("width", "200%");
var width = $(this).width();
$(this).css("position", "");
$(this).parent().css("position", "").css("width", "");
//Don't do anything if it fits
if (width < maxWidth) {
return;
}
//Check how many times the container fits within the box
var times = Math.ceil(width / maxWidth);
//Function for cleaning chunks
var cleanChunk = function (chunk) {
var thisChunkLength = chunk.length - 1;
if (chunk[0] == " ") chunk = chunk.substring(1);
if (chunk[thisChunkLength] == " ") chunk = chunk.substring(0, thisChunkLength);
return chunk;
};
//Divide the text into chunks
var text = $(this).html();
var textArr = text.split(" ");
var chunkLength = Math.ceil((textArr.length - 1) / times);
var chunks = [];
var curChunk = "";
var curChunkCount = 0;
var isParsingHtml = false;
//Loop through the text array and split it into chunks
for (var i in textArr) {
//When we are parsing HTML we don't want to count the
//spaces since the user doesn't see it.
if (isParsingHtml) {
//Check for a HTML end tag
if (/<\/[a-zA-Z]*>/.test(textArr[i]) || /[a-zA-Z]*>/.test(textArr[i])) {
isParsingHtml = false;
}
} else {
//Check for a HTML begin tag
if (/<[a-zA-Z]*/.test(textArr[i])) {
isParsingHtml = true;
}
}
//Calculate chunks
if (curChunkCount == (chunkLength - 1) && !isParsingHtml) {
curChunk += textArr[i] + " ";
chunks.push(cleanChunk(curChunk));
curChunk = "";
curChunkCount = -1;
} else if ((i == (textArr.length - 1))) {
curChunk += textArr[i];
chunks.push(cleanChunk(curChunk));
break;
} else {
curChunk += textArr[i] + " ";
}
if (!isParsingHtml) {
curChunkCount++;
}
}
//Convert chunks to new elements
var el = $($(this).html("").outerHTML());
for (var x in chunks) {
var new_el = el.clone().html(chunks[x]).addClass("text-render-el");
var new_el_container = $("<div/>").addClass("text-render-container");
new_el_container.append(new_el);
$(this).before(new_el_container);
}
//Finally remove the current element
$(this).remove();
});
};
Thats the problem you get when using templates, ive programmed a site in php, but the design is killing me.
So i try'd some rocket fuel for webdesigners.
And this is the problems i keep getting every step of the way...
Inline-block does not work for me, nothing works, becouse it is not my design and i dont know the setup.
Ive tryd doing the design myself, but i am out of time, i need a design yesterday.
I suggest you take what u need from the templates and delete everything else, that will schrink your problem, and save you time.

Resources