<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
<title>履歴付き電卓</title>
<style>
/* 基本設定 */
* {
box-sizing: border-box;
touch-action: manipulation;
-webkit-tap-highlight-color: transparent;
}
body {
margin: 0;
padding: 0;
height: 100dvh;
width: 100vw;
display: flex;
flex-direction: column;
background-color: #000;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
overflow: hidden;
}
/* 画面上部エリア(履歴+メイン表示) */
#display-container {
flex: 1; /* 残りのスペースを全て使う */
display: flex;
flex-direction: column;
justify-content: flex-end; /* 下に詰める */
padding: 20px;
padding-bottom: 10px;
overflow: hidden; /* 全体のはみ出しを隠す */
}
/* 履歴表示エリア(新設) */
#history {
width: 100%;
/* 残りの空間を履歴が埋める */
flex: 1;
overflow-y: auto; /* 履歴が多いとスクロール */
display: flex;
flex-direction: column;
justify-content: flex-end; /* 新しい履歴が下に来る */
align-items: flex-end; /* 右詰め */
/* 文字設定 */
color: #888; /* 薄いグレーにして目立たなくする */
font-size: 0.9rem; /* かなり小さく */
line-height: 1.4;
padding-bottom: 5px;
margin-bottom: 5px;
border-bottom: 1px solid #333; /* 境界線を薄く引く */
}
/* 履歴の各行 */
.history-item {
font-family: monospace; /* 等幅フォントで計算っぽく */
}
/* メイン数値表示部分 */
#display {
width: 100%;
color: white;
font-size: 3.5rem;
font-weight: 300;
text-align: right;
word-break: break-all;
line-height: 1.1;
/* 【重要】2行制限の設定 */
max-height: calc(3.5rem * 1.1 * 2); /* 文字サイズ×行間×2行 */
overflow-y: auto; /* 2行を超えたらこの中でスクロール */
flex-shrink: 0; /* 履歴に押しつぶされないように固定 */
}
/* スクロールバーを隠す(見た目をきれいに) */
#display::-webkit-scrollbar, #history::-webkit-scrollbar {
display: none;
}
/* ボタンエリア(前回と同じ設定) */
.buttons {
height: 55%;
padding-bottom: env(safe-area-inset-bottom);
margin-bottom: 10px;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(5, 1fr);
gap: 8px;
padding-left: 15px;
padding-right: 15px;
}
button {
border: none;
font-size: 1.7rem;
border-radius: 1000px;
cursor: pointer;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
transition: all 0.1s;
height: 100%;
}
button:active {
filter: brightness(0.8);
transform: scale(0.98);
}
.number { background-color: #333333; }
.operator { background-color: #ff9f0a; font-size: 2.2rem; }
.func { background-color: #a5a5a5; color: black; font-weight: 500; }
.zero-btn {
grid-column: span 2;
justify-content: flex-start;
padding-left: 30px;
}
.time-btn {
background-color: #a5a5a5;
color: black;
font-size: 1.2rem;
font-weight: bold;
}
</style>
</head>
<body>
<div id="display-container">
<div id="history"></div>
<div id="display">0</div>
</div>
<div class="buttons">
<button class="func" onclick="clearDisplay()">C</button>
<button class="func" onclick="deleteLast()">←</button>
<button class="time-btn" id="btn-time" onclick="cycleTime()">分</button>
<button class="operator" onclick="appendDisplay('/')">÷</button>
<button class="number" onclick="appendDisplay('7')">7</button>
<button class="number" onclick="appendDisplay('8')">8</button>
<button class="number" onclick="appendDisplay('9')">9</button>
<button class="operator" onclick="appendDisplay('*')">×</button>
<button class="number" onclick="appendDisplay('4')">4</button>
<button class="number" onclick="appendDisplay('5')">5</button>
<button class="number" onclick="appendDisplay('6')">6</button>
<button class="operator" onclick="appendDisplay('-')">−</button>
<button class="number" onclick="appendDisplay('1')">1</button>
<button class="number" onclick="appendDisplay('2')">2</button>
<button class="number" onclick="appendDisplay('3')">3</button>
<button class="operator" onclick="appendDisplay('+')">+</button>
<button class="number zero-btn" onclick="appendDisplay('0')">0</button>
<button class="number" onclick="appendDisplay('.')">.</button>
<button class="operator" onclick="calculateResult()">=</button>
</div>
<script>
const display = document.getElementById('display');
const historyDiv = document.getElementById('history');
const btnTime = document.getElementById('btn-time');
const operators = ['/', '*', '-', '+'];
const unitNames = ["分", "時間", "日", "年", "秒"];
let timeState = 0;
function getDisplayValue() {
return display.innerText;
}
function setDisplayValue(val) {
display.innerText = val;
}
// 履歴に追加する関数
function addHistory(text) {
const item = document.createElement('div');
item.className = 'history-item';
item.innerText = text;
historyDiv.appendChild(item);
// 常に最新の履歴が見えるようにスクロール
historyDiv.scrollTop = historyDiv.scrollHeight;
}
function appendDisplay(input) {
const currentVal = getDisplayValue();
const lastChar = currentVal.slice(-1);
if (currentVal === '0' && !operators.includes(input) && input !== '.') {
setDisplayValue(input);
return;
}
if (operators.includes(input) && operators.includes(lastChar)) {
return;
}
setDisplayValue(currentVal + input);
}
function clearDisplay() {
setDisplayValue("0");
// Cボタンでは履歴は消さない仕様にしています
}
function deleteLast() {
const currentVal = getDisplayValue();
if (currentVal.length > 1) {
setDisplayValue(currentVal.slice(0, -1));
} else {
setDisplayValue("0");
}
}
function cycleTime() {
try {
let val = parseFloat(eval(getDisplayValue()));
if (timeState === 0) val = val / 60;
else if (timeState === 1) val = val / 24;
else if (timeState === 2) val = val / 365;
else if (timeState === 3) val = val * 365 * 24 * 60 * 60;
else if (timeState === 4) val = val / 60;
timeState++;
if (timeState >= unitNames.length) timeState = 0;
setDisplayValue(val);
updateUnitDisplay();
} catch (e) {
setDisplayValue("Error");
}
}
function updateUnitDisplay() {
btnTime.innerText = unitNames[timeState];
}
function calculateResult() {
try {
let expression = getDisplayValue();
// 計算実行
let result = new Function('return ' + expression)();
// 履歴に追加 (式 = 答え)
// ※見やすくするため、内部的な「*」を「×」などに置換して表示しても良いですが
// 今回はシンプルにそのまま表示します
if (expression !== String(result)) { // 既に計算済みの場合は履歴に残さない
addHistory(expression + " = " + result);
}
setDisplayValue(result);
} catch (error) {
setDisplayValue("Error");
}
}
</script>
</body>
</html>
使用変数
| addHistory -------( Function ) | |
| appendDisplay -------( Function ) | |
| btnTime | |
| calculateResult -------( Function ) | |
| charset | |
| class | |
| className | |
| clearDisplay -------( Function ) | |
| content | |
| currentVal | |
| cycleTime -------( Function ) | |
| deleteLast -------( Function ) | |
| display | |
| expression | |
| fit | |
| getDisplayValue -------( Function ) | |
| historyDiv | |
| id | |
| innerText | |
| item | |
| lang | |
| lastChar | |
| name | |
| onclick | |
| operators | |
| result | |
| scalable | |
| scale | |
| scrollTop | |
| setDisplayValue -------( Function ) | |
| timeState | |
| unitNames | |
| updateUnitDisplay -------( Function ) | |
| val | |
| width | |
| 式 |